/* * Copyright © 2014 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.Batch; import co.cask.cdap.api.annotation.Output; import co.cask.cdap.api.annotation.ProcessInput; import co.cask.cdap.api.annotation.Tick; import co.cask.cdap.api.app.AbstractApplication; import co.cask.cdap.api.flow.AbstractFlow; import co.cask.cdap.api.flow.flowlet.AbstractFlowlet; import co.cask.cdap.api.flow.flowlet.InputContext; import co.cask.cdap.api.flow.flowlet.OutputEmitter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Iterator; import java.util.concurrent.TimeUnit; /** * */ public final class GenSinkApp2 extends AbstractApplication { @Override public void configure() { setName("GenSinkApp"); setDescription("GenSinkApp desc"); addFlow(new GenSinkFlow()); } /** * */ public static final class GenSinkFlow extends AbstractFlow { @Override protected void configureFlow() { setName("GenSinkFlow"); setDescription("GenSinkFlow desc"); addFlowlet(new GenFlowlet()); addFlowlet(new SinkFlowlet()); addFlowlet(new BatchSinkFlowlet()); connect(new GenFlowlet(), new SinkFlowlet()); connect(new GenFlowlet(), new BatchSinkFlowlet()); } } /** * @param <T> * @param <U> */ public abstract static class GenFlowletBase<T, U> extends AbstractFlowlet { protected OutputEmitter<T> output; @Output("batch") protected OutputEmitter<U> batchOutput; @Tick(delay = 1L, unit = TimeUnit.DAYS) public void generate() throws Exception { // No-op } } /** * */ public static final class GenFlowlet extends GenFlowletBase<String, Integer> { private int i; @Tick(delay = 1L, unit = TimeUnit.NANOSECONDS) public void generate() throws Exception { if (i < 100) { output.emit("Testing " + ++i); batchOutput.emit(i); if (i == 10) { throw new IllegalStateException("10 hitted"); } } } } /** * @param <T> * @param <U> */ public abstract static class SinkFlowletBase<T, U> extends AbstractFlowlet { private static final Logger LOG = LoggerFactory.getLogger(SinkFlowletBase.class); @ProcessInput public void process(T event, InputContext context) throws InterruptedException { LOG.info(event.toString()); } @ProcessInput public void process(T event) throws InterruptedException { // This method would violate the flowlet construct as same input name for same input type. // Children classes would override this without the @ProcessInput } @Batch(10) @ProcessInput("batch") public void processBatch(U event) { LOG.info(event.toString()); } } /** * */ public static final class SinkFlowlet extends SinkFlowletBase<String, Integer> { @ProcessInput public void process(String event, InputContext context) throws InterruptedException { super.process(event, context); } @Override public void process(String event) throws InterruptedException { // Nothing. Just override to avoid deployment failure. } } /** * Consume batch event of type integer. This is for batch consume with Iterator. */ public static final class BatchSinkFlowlet extends AbstractFlowlet { private static final Logger LOG = LoggerFactory.getLogger(BatchSinkFlowlet.class); @Batch(10) @ProcessInput("batch") public void processBatch(Iterator<Integer> events) { while (events.hasNext()) { LOG.info("Iterator batch: {}", events.next().toString()); } } } }