Files
spring-cloud-dataflow-samples/custom-apps/celsius-converter-processor
mross1080 84d872204b New sample README demonstrating a Spring Cloud Stream processor
* Shows how to create a simple Spring Cloud Stream processor
  that converts temperatrues from Fahrenheit to Celsius
* Shows how to run it both as a standalone Spring Boot microservice
  and then on Spring Cloud Data Flow as part of a stream.

Polishing the PR
2017-10-12 11:25:18 -04:00
..

# Custom Spring Cloud Stream Processor
=======================================

### Creating the project

Today we're going to talk about how to create a custom Spring Cloud Stream application and running it on Spring Cloud Data Flow.
We're going to go through all the steps for making a simple processor that will allow you to convert 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.
The first step is to create a new spring cloud stream project.
We can do that by going to http://start.spring.io/, which is the spring initializer.

Choose the group as `demo.celsius.converter` and enter artifact name as celsius-converter-processor.
Next, we need to choose a message transport binding as a dependency for the custom app.
There are options for choosing ***rabbitmq*** or ***kafka*** as the message transport.
For this demo, we choose rabbit by typing rabbit in the search bar under "Search for dependencies" and then selecting "stream rabbit".

Hit the generate project button and then open the new project in an IDE of your choice.

### Developing the app

Now we're at a point where we can actually create our custom app. In our Spring Cloud Stream application, the minimum configuration is going to require two Java class files.
* CelsiusConverterProcessorAplication.java
* CelsiusConverterProcessorConfiguration.java

Spring Cloud Stream applications are stand alone spring boot applications that can be run on their own.
Spring Cloud Data Flow is the orchestration layer that ties these individual Spring Cloud Stream apps together.

Since we named the project as celsius-converter-processor, the initializer created a class called CelsiusConverterProcessorAplication.
We are creating a transformer that takes a Fahrenheit input and converts it to Celsius.
We want to follow the same naming convention as the application file, so create a new file in the same directory called `CelsiusConverterProcessorConfiguration.java`.

##### CelsiusConverterProcessorConfiguration.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-30)/2;
    }
}
```

There are two important spring annotations that we introduced in the above code.
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 are basically classifying this stream app as a Processor(as opposed to a source or a sink).
This allows us to specify that the application is receiving input from upstream(Processor.input) and send the output data downstream(Processor.OUTPUT).

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 proper Spring Cloud Stream processor.

Once we're done putting together the app, move into the origin of the project directory and build a deployable jar with Maven, possibly on the command line.
```
cd <PATH/TO/PROJECT>
mvn clean install

Make sure you have a running instance of RabbitMQ https://www.rabbitmq.com/

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 Locally on Spring Cloud Data Flow

#### Prerequisites

In order to get started, make sure that you have the following components:

* Local build of https://github.com/spring-cloud/spring-cloud-dataflow [Spring Cloud Data Flow]
* Running instance of RabbitMQ https://www.rabbitmq.com/


 Launch the locally built `server`

```
$ cd <PATH/TO/SPRING-CLOUD-DATAFLOW>
$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-<VERSION>.jar
```

Connect to Spring Cloud Data Flow's `shell`

```
$ cd <PATH/TO/SPRING-CLOUD-DATAFLOW>
$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-<VERSION>.jar

  ____                              ____ _                __
 / ___| _ __  _ __(_)_ __   __ _   / ___| | ___  _   _  __| |
 \___ \| '_ \| '__| | '_ \ / _` | | |   | |/ _ \| | | |/ _` |
  ___) | |_) | |  | | | | | (_| | | |___| | (_) | |_| | (_| |
 |____/| .__/|_|  |_|_| |_|\__, |  \____|_|\___/ \__,_|\__,_|
  ____ |_|    _          __|___/                 __________
 |  _ \  __ _| |_ __ _  |  ___| | _____      __  \ \ \ \ \ \
 | | | |/ _` | __/ _` | | |_  | |/ _ \ \ /\ / /   \ \ \ \ \ \
 | |_| | (_| | || (_| | |  _| | | (_) \ V  V /    / / / / / /
 |____/ \__,_|\__\__,_| |_|   |_|\___/ \_/\_/    /_/_/_/_/_/

<VERSION>

Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help".
dataflow:>version
<VERSION>
```


[Register](https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app) RabbitMQ binder variant of out-of-the-box applications
```
dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven
```

```
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 want to create a stream that uses the out of the box apps `http` and `log` and then connect them with our custom celsius converter app.

```
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
```

Since we are running locally, note the file location of the logs.


```
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 pointing to the `http` endpoint: `http://localhost:9090` [`9090` is the `server.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
```
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                                 : 23
```

In conclusion, we created a simple Spring Cloud Stream processor that converts the incoming Fahrenheit temperature data to Celsius.
We ran it first as a standalone Spring Boot microservice application and then took the same app to Spring Cloud Data Flow to orchestrate it to be part of a stream that contains other apps.