[[spring-cloud-data-flow-samples-custom-application-overview]]
:sectnums:
:docs_dir: ../../..

=== Custom Spring Cloud Stream Processor

==== Prerequisites
* A Running Data Flow Shell
include::{docs_dir}/shell.adoc[]
* A running local Data Flow Server
include::{docs_dir}/local-server.adoc[]
* A Java IDE
* https://maven.apache.org/[Maven] Installed
* A running instance of https://www.rabbitmq.com/[Rabbit MQ]

==== Creating the Custom Stream App
We will create a custom https://cloud.spring.io/spring-cloud-stream/[Spring Cloud Stream] application and run it on Spring Cloud Data Flow.
We'll go through the steps to make a simple processor that converts temperature from Fahrenheit to Celsius.
We will be running the demo locally, but all the steps will work in a Cloud Foundry environment as well.

. Create a new spring cloud stream project
+
* Create a https://start.spring.io/[Spring initializer] project

* Set the group to `demo.celsius.converter` and the artifact name as `celsius-converter-processor`

* Choose a message transport binding as a dependency for the custom app
There are options for choosing `Rabbit MQ` or `Kafka` as the message transport.
For this demo, we will use `rabbit`. Type _rabbit_ in the search bar under _Search for dependencies_ and select `Stream Rabbit`.

* Hit the generate project button and open the new project in an IDE of your choice
+
. Develop the app
+
We can now create our custom app. Our Spring Cloud Stream application is a Spring Boot application that runs as an executable jar. The application will include two Java classes:

* `CelsiusConverterProcessorAplication.java` - the main Spring Boot application class, generated by Spring initializr

* `CelsiusConverterProcessorConfiguration.java` - the Spring Cloud Stream code that we will write
+
We are creating a transformer that takes a Fahrenheit input and converts it to Celsius.
Following the same naming convention as the application file, create a new Java class in the same package called `CelsiusConverterProcessorConfiguration.java`.
+
.CelsiusConverterProcessorConfiguration.java
[source,java]
```
@EnableBinding(Processor.class)
public class CelsiusConverterProcessorConfiguration {

    @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
    public int convertToCelsius(String payload) {
        int fahrenheitTemperature = Integer.parseInt(payload);
        return (farenheitTemperature-32)*5/9;
    }
}
```
+
Here we introduced two important Spring annotations.
First we annotated the class with `@EnableBinding(Processor.class)`.
Second we created a method and annotated it with `@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)`.
By adding these two annotations we have configured this stream app as a `Processor` (as opposed to a `Source` or a `Sink`).
This means that the application receives input from an upstream application via the `Processor.INPUT` channel and sends its output to a downstream application via the `Processor.OUTPUT` channel.
+
The `convertToCelsius` method takes a `String` as input for Fahrenheit and then returns the converted Celsius as an integer.
This method is very simple, but that is also the beauty of this programming style.
We can add as much logic as we want to this method to enrich this processor.
As long as we annotate it properly and return valid output, it works as a Spring Cloud Stream Processor. Also note that it is straightforward to unit test this code.
+
. Build the Spring Boot application with Maven
+
```
$cd <PROJECT_DIR>
$./mvnw clean package
```
+
. Run the Application standalone
+
```
java -jar target/celsius-converter-processor-0.0.1-SNAPSHOT.jar
```
+
If all goes well, we should have a running standalone Spring Boot Application.
Once we verify that the app is started and running without any errors, we can stop it.

==== Deploying the App to Spring Cloud Data Flow

. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder
+
include::{docs_dir}/maven-access.adoc[]
+
[subs="attributes"]
```
dataflow:>app import --uri {app-import-rabbit-maven}
```
+
+
. Register the custom processor
+
```
app register --type processor --name convertToCelsius --uri <File URL of the jar file on the local filesystem where you built the project above> --force
```
+
. Create the stream
+
We will create a stream that uses the out of the box `http` source and `log` sink and our custom transformer.
+
```
dataflow:>stream create --name convertToCelsiusStream --definition "http  --port=9090 | convertToCelsius | log" --deploy

Created and deployed new stream 'convertToCelsiusStream'
```
+
. Verify the stream is successfully deployed
+
```
dataflow:>stream list
```
+
. Verify that the apps have successfully deployed
+
```
dataflow:>runtime apps
```
+
.Note the file location of the application logs
+
[source,console,options=nowrap]
----
2016-09-27 10:03:11.988  INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer       : deploying app convertToCelsiusStream.log instance 0
   Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984991968/convertToCelsiusStream.log
2016-09-27 10:03:12.397  INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer       : deploying app convertToCelsiusStream.convertToCelsius instance 0
   Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984992392/convertToCelsiusStream.convertToCelsius
2016-09-27 10:03:14.445  INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer       : deploying app convertToCelsiusStream.http instance 0
   Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984994440/convertToCelsiusStream.http
----
+
. Post sample data to the `http` endpoint: `http://localhost:9090` (`9090` is the `port` we specified for the `http` source in this case)
+

```
dataflow:>http post --target http://localhost:9090 --data 76
> POST (text/plain;Charset=UTF-8) http://localhost:9090 76
> 202 ACCEPTED
```
+
. Open the log file for the `convertToCelsiusStream.log` app to see the output of our stream
+
[source,console,options=nowrap]
----
tail -f /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-7563139704229890655/convertToCelsiusStream-1474990317406/convertToCelsiusStream.log/stdout_0.log
----
+
You should see the temperature you posted converted to Celsius!
```
2016-09-27 10:05:34.933  INFO 95616 --- [CelsiusStream-1] log.sink                                 : 24
```

==== Summary
In this sample, you have learned:

* How to write a custom `Processor` stream application
* How to use Spring Cloud Data Flow's `Local` server
* How to use Spring Cloud Data Flow's `shell` application
