/* * Copyright © 2014-2015 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.test.app; import co.cask.cdap.api.annotation.ProcessInput; import co.cask.cdap.api.annotation.Tick; import co.cask.cdap.api.annotation.UseDataSet; import co.cask.cdap.api.app.AbstractApplication; import co.cask.cdap.api.data.stream.Stream; import co.cask.cdap.api.dataset.lib.KeyValueTable; import co.cask.cdap.api.flow.AbstractFlow; import co.cask.cdap.api.flow.flowlet.AbstractFlowlet; import co.cask.cdap.api.flow.flowlet.OutputEmitter; import co.cask.cdap.api.flow.flowlet.StreamEvent; import co.cask.cdap.api.service.BasicService; import co.cask.cdap.api.service.http.AbstractHttpServiceHandler; import co.cask.cdap.api.service.http.HttpServiceRequest; import co.cask.cdap.api.service.http.HttpServiceResponder; import com.google.common.base.Charsets; import java.io.IOException; import java.util.concurrent.TimeUnit; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; /** * */ public class JoinMultiStreamApp extends AbstractApplication { /** * */ public static final class Entry { byte[] name; byte[] value; Entry(String name, String value) { this.name = name.getBytes(Charsets.UTF_8); this.value = value.getBytes(Charsets.UTF_8); } } @Override public void configure() { setName("JoinMulti"); setDescription("JoinMulti"); addStream(new Stream("s1")); addStream(new Stream("s2")); addStream(new Stream("s3")); createDataset("mytable", KeyValueTable.class); addFlow(new JoinMultiFlow()); addService(new BasicService("QueryService", new QueryHandler())); } /** * */ public static class JoinMultiFlow extends AbstractFlow { @Override protected void configureFlow() { setName("JoinMultiFlow"); setDescription("JoinMultiFlow"); addFlowlet(new StreamSource("input1")); addFlowlet(new StreamSource("input2")); addFlowlet(new StreamSource("input3")); addFlowlet(new Terminal()); connectStream("s1", "input1"); connectStream("s2", "input2"); connectStream("s3", "input3"); connect("input1", "Terminal"); connect("input2", "Terminal"); connect("input3", "Terminal"); } } /** * */ public static class StreamSource extends AbstractFlowlet { private final String name; private OutputEmitter<Entry> output; public StreamSource(String name) { this.name = name; } @ProcessInput public void process(StreamEvent event) { output.emit(new Entry(getContext().getName(), Charsets.UTF_8.decode(event.getBody()).toString())); } @Override protected void configure() { setName(name); } } /** * */ public static class Terminal extends AbstractFlowlet { @UseDataSet("mytable") private KeyValueTable table; @ProcessInput public void process(Entry entry) { table.write(entry.name, entry.value); } @Tick(delay = 5L, unit = TimeUnit.MINUTES) public void tick() { // The tick method is to test tick doesn't affect process method trigger. } } /** * */ public static class QueryHandler extends AbstractHttpServiceHandler { @UseDataSet("mytable") private KeyValueTable table; @GET @Path("{key}") public void handle(HttpServiceRequest request, HttpServiceResponder responder, @PathParam("key") String key) throws IOException { byte[] result = table.read(key.getBytes(Charsets.UTF_8)); if (result == null) { responder.sendError(404, "Key not found: " + key); return; } String value = new String(result, Charsets.UTF_8); responder.sendJson(value); } } }