/*
* 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.examples.helloworld;
import co.cask.cdap.api.annotation.ProcessInput;
import co.cask.cdap.api.annotation.UseDataSet;
import co.cask.cdap.api.app.AbstractApplication;
import co.cask.cdap.api.common.Bytes;
import co.cask.cdap.api.data.stream.Stream;
import co.cask.cdap.api.dataset.DatasetProperties;
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.StreamEvent;
import co.cask.cdap.api.metrics.Metrics;
import co.cask.cdap.api.service.AbstractService;
import co.cask.cdap.api.service.Service;
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 javax.ws.rs.GET;
import javax.ws.rs.Path;
/**
* This is a simple HelloWorld example that uses one stream, one dataset, one flow and one service.
* <uL>
* <li>A stream to send names to.</li>
* <li>A flow with a single flowlet that reads the stream and stores each name in a KeyValueTable</li>
* <li>A service that reads the name from the KeyValueTable and responds with 'Hello [Name]!'</li>
* </uL>
*/
public class HelloWorld extends AbstractApplication {
@Override
public void configure() {
setName("HelloWorld");
setDescription("A Hello World program for the Cask Data Application Platform");
addStream(new Stream("who"));
createDataset("whom", KeyValueTable.class, DatasetProperties.builder().setDescription("Store names").build());
addFlow(new WhoFlow());
addService(new Greeting());
}
/**
* Sample Flow.
*/
public static final class WhoFlow extends AbstractFlow {
@Override
protected void configure() {
setName("WhoFlow");
setDescription("A flow that collects names");
addFlowlet("saver", new NameSaver());
connectStream("who", "saver");
}
}
/**
* Sample Flowlet.
*/
public static final class NameSaver extends AbstractFlowlet {
static final byte[] NAME = { 'n', 'a', 'm', 'e' };
@UseDataSet("whom")
private KeyValueTable whom;
private Metrics metrics;
@ProcessInput
public void process(StreamEvent event) {
byte[] name = Bytes.toBytes(event.getBody());
if (name.length > 0) {
whom.write(NAME, name);
if (name.length > 10) {
metrics.count("names.longnames", 1);
}
metrics.count("names.bytes", name.length);
}
}
}
/**
* A {@link Service} that creates a greeting using a user's name.
*/
public static final class Greeting extends AbstractService {
public static final String SERVICE_NAME = "Greeting";
@Override
protected void configure() {
setName(SERVICE_NAME);
setDescription("Service that creates a greeting using a user's name.");
addHandler(new GreetingHandler());
}
}
/**
* Greeting Service handler.
*/
public static final class GreetingHandler extends AbstractHttpServiceHandler {
@UseDataSet("whom")
private KeyValueTable whom;
private Metrics metrics;
@Path("greet")
@GET
public void greet(HttpServiceRequest request, HttpServiceResponder responder) {
byte[] name = whom.read(NameSaver.NAME);
String toGreet = name != null ? new String(name, Charsets.UTF_8) : "World";
if (toGreet.equals("Jane Doe")) {
metrics.count("greetings.count.jane_doe", 1);
}
responder.sendString(String.format("Hello %s!", toGreet));
}
}
}