diff --git a/custom-apps/celsius-converter-processor/README.adoc b/custom-apps/celsius-converter-processor/README.adoc new file mode 100644 index 0000000..99d3f99 --- /dev/null +++ b/custom-apps/celsius-converter-processor/README.adoc @@ -0,0 +1,172 @@ +# 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 +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 +$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar +``` + +Connect to Spring Cloud Data Flow's `shell` + +``` +$ cd +$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar + + ____ ____ _ __ + / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | + \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | + ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | + |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| + ____ |_| _ __|___/ __________ + | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ + | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ + | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / + |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ + + + +Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". +dataflow:>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 --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.