About Bilgin Ibryam

Bilgin Ibryam is a senior software engineer based in London interested in service-oriented architecture, enterprise application integration and application development. He is also open source enthusiast, Apache Open for Business and Apache Camel committer.

A Camel Demo for Amazon’s Simple Worklfow Service

In a previous post I explained why AWS SWF service is good and announced the new Camel SWF component. Now the component documentation is ready and here is a simplistic fully working demo. It consist of three independent standalone Camel routes:
A workflow producer allows us to interact with a workflow. It can start a new workflow execution, query its state, send signals to a running workflow, or terminate and cancel it. In our demo, the WorkflowProducer starts a route that schedules 10 workflow executions where the each execution receives as an argument a number.
 
 
 

package com.ofbizian.swf.demo;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;

public class WorkflowProducer {

    public static String COMMON_OPTIONS =
        "accessKey=XXX"
        + "&secretKey=XXX"
        + "&domainName=demo"
        + "&workflowList=demo-wlist"
        + "&activityList=demo-alist"
        + "&version=1.0"
        + "&clientConfiguration.endpoint=swf.eu-west-12.amazonaws.com";

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.enableHangupSupport();
        WorkflowProducerRoute route = new WorkflowProducerRoute();
        main.addRouteBuilder(route);
        main.run();
    }

    static class WorkflowProducerRoute extends RouteBuilder {

        @Override
        public void configure() throws Exception {

            from("timer://workflowProducer?repeatCount=10")
                    .setBody(property("CamelTimerCounter"))
                    .to("aws-swf://workflow?" + COMMON_OPTIONS + "&eventName=calculator")
                    .log("SENT WORKFLOW TASK ${body}");
        }
    }
}

Once a workflow execution is scheduled, we need a process that will decide what are the next steps for it. In Camel it is done using a Workflow Consumer. A workflow consumer represents the workflow logic. When it is started, it will start polling workflow decision tasks and process them. In addition to processing decision tasks, a workflow consumer route, will also receive signals (send from a workflow producer) or state queries. The primary purpose of a workflow consumer is to schedule activity tasks for execution using activity producers. Actually activity tasks can be scheduled only from a thread started by a workflow consumer.

package com.ofbizian.swf.demo;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.aws.swf.SWFConstants;
import org.apache.camel.main.Main;

public class WorkflowConsumer {

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.enableHangupSupport();
        WorkflowConsumerRoute route = new WorkflowConsumerRoute();
        main.addRouteBuilder(route);
        main.run();
    }

    static class WorkflowConsumerRoute extends RouteBuilder {

        @Override
        public void configure() throws Exception {

            from("aws-swf://workflow?" + WorkflowProducer.COMMON_OPTIONS + "&eventName=calculator")

                    .choice()
                        .when(header(SWFConstants.ACTION).isEqualTo(SWFConstants.SIGNAL_RECEIVED_ACTION))
                            .log("Signal received ${body}")

                        .when(header(SWFConstants.ACTION).isEqualTo(SWFConstants.GET_STATE_ACTION))
                            .log("State asked ${body}")

                        .when(header(SWFConstants.ACTION).isEqualTo(SWFConstants.EXECUTE_ACTION))

                            .setBody(simple("${body[0]}"))
                            .log("EXECUTION TASK RECEIVED ${body}")

                            .filter(simple("${body} > 5"))
                                .to("aws-swf://activity?" + WorkflowProducer.COMMON_OPTIONS + "&eventName=incrementor");
        }
    }

}

The logic in our demo decider is simple: if the incoming argument is greater than 5, we schedule a task for execution. Otherwise the workflow will complete as there are no other tasks to be executed. Notice that it also has branches for handing signal and state query events.

The final peace of our distributed (since it consists of three independent applications) workflow application is the ActivityConsumer that actually performs some calculations. It has the simplest possible implementation: increments the given argument and returns it.

package com.ofbizian.swf.demo;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;

public class ActivityConsumer {

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.enableHangupSupport();
        ActivityConsumerRoute route = new ActivityConsumerRoute();
        main.addRouteBuilder(route);
        main.run();
    }

    static class ActivityConsumerRoute extends RouteBuilder {

        @Override
        public void configure() throws Exception {
from("aws-swf://activity?" + WorkflowProducer.COMMON_OPTIONS + "&eventName=incrementor")
                    .setBody(simple("${body[0]}"))
                    .log("RECEIVED ACTIVITY TASK ${body}")
                    .setBody(simple("${body}++"));
        }
    }
}

All you need to do to run this demo is to create the appropriate workflow domain and add your key/secret to the route.
 

Reference: A Camel Demo for Amazon’s Simple Worklfow Service from our JCG partner Bilgin Ibryam at the OFBIZian blog.
Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


× 5 = forty



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books