Using Activiti with Camel
In this example we show an example howto Activiti can be used with Camel in Servicemix through Blueprint Container
http://aries.apache.org/modules/blueprint.html
Before being able to run Activiti with Camel, you have to install some additional
features into the container first to add support for the Activiti.
karaf@root> features:install activiti
By default in Servicemix Activiti Engine use an Embedded (Local) H2 Database the can be found under
${karaf.data}/activiti/database.
The Activiti engine is entry point for starting new process instances, deploy new process, querying for
user tasks ecc.ecc and these information are stored in H2 DataBase
Blueprint configuration
Let's see how you can set up the Camel context in a Blueprint configuration, as you can see
Camel integration runs embedded with the Activiti Engine in the same Blueprint configuration.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:camel="http://camel.apache.org/schema/blueprint">
<!--
This Camel context contains the routes that interact with our BPMN process
Here we instruct the Camel context to scan the classpath in
org.apache.servicemix.examples.activiti
-->
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/blueprint">
<packageScan>
<package>org.apache.servicemix.examples.activiti</package>
</packageScan>
</camelContext>
<!--
Obtain a reference to Activiti's RuntimeService - this reference will automatically
be picked up by the subsequent Activiti Camel component definition
-->
<reference id="runtimeService" interface="org.activiti.engine.RuntimeService" />
<!--
Register a context provider to link the Camel context to the OrderProcess definition.
Doing this will allow your BPMN process to communicate with the Camel routes using the
${camel} expression
The definition of SimpleContextProvider allows to connects a deployed process definition on the Activiti Engine to a Camel context.
Is possible to define a list of SimpleContextProviders for each process definition that you want to connect to a Camel contex
-->
<service interface="org.activiti.camel.ContextProvider">
<bean class="org.activiti.camel.SimpleContextProvider">
<argument value="OrderProcess"/>
<argument ref="camelContext"/>
</bean>
</service>
</blueprint>
Route Definition
/**
* Camel routes that interact with the business process defined in the
* OSGI-INF/activiti/OrderProcess.bpmn20.xml file
*/
public class ActivitiRouteBuilder extends RouteBuilder {
private final Helper helper = new Helper();
@Override
public void configure() throws Exception {
/*
* This route will start a new OrderProcess instance. Using the PROCESS_KEY_PROPERTY, we are assigning a
* business key to our process to allow for easier correlation in later processing steps. We are also
* sending a Map containing additional variables to add to the process instance.
*/
from("file:var/activiti-camel/order")
.setBody(bean(helper))
.setProperty(PROCESS_KEY_PROPERTY, simple("file:name"))
.to("activiti:OrderProcess")
.log("Process to handle incoming order file has been started (process instance id ${body})");
/*
* This route will notify a running OrderProcess of an order delivery event. Here too, we are setting the
* PROCESS_KEY_PROPERTY to correlate the delivery message with right order process instance.
*/
from("file:var/activiti-camel/delivery")
.log("Notifying process about delivery for order ${file:name}")
.setProperty(PROCESS_KEY_PROPERTY, simple("file:name"))
.to("activiti:OrderProcess:receiveDelivery");
/*
* The BPMN process can also trigger Camel routes as part of the process. In these routes, the variables that
* you added to the process are available as Exchange properties. The next two routes will be triggered while
* processing the order and the order delivery.
*/
from("activiti:OrderProcess:processOrder")
.log("Processing order ${property.orderid} created on ${property:timestamp}")
.log(" original message: ${property.message}");
from("activiti:OrderProcess:processDelivery")
.log("Processing delivery for order ${property.orderid} created on ${property:timestamp}")
.log(" original message: ${property.message}");
}
/*
* A few helper methods used for routing
*/
public static final class Helper {
/*
* This method will extract information from the Exchange (using Camel annotations) and put them in a
* Map that will be used for setting up the process' variables.
*/
@Handler
public Map getProcessVariables(@Body String body,
@Header(Exchange.FILE_NAME) String filename,
@Simple("${date:now:yyyy-MM-dd kk:mm:ss}") String timestamp) {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("message", body);
variables.put("orderid", filename);
variables.put("timestamp", timestamp);
return variables;
}
}
}
Process definition
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="OrderProcess" isExecutable="true">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="processOrder" />
<serviceTask id="processOrder"
activiti:delegateExpression="${camel}" />
<sequenceFlow id="flow2" sourceRef="processOrder"
targetRef="receiveDelivery" />
<receiveTask id="receiveDelivery" name="Wait for Delivery" />
<sequenceFlow id="flow3" sourceRef="receiveDelivery"
targetRef="processDelivery" />
<serviceTask id="processDelivery"
activiti:delegateExpression="${camel}" />
<sequenceFlow id="flow4" sourceRef="processDelivery"
targetRef="end" />
<endEvent id="end" />
</process>
</definitions>
The process presented here above define a simple order process, that process the incoming orders and subsequently waits for its delivery. Once the delivery notification has been received,
another bit of processing occurs before the business process ends.
This process defines the BPMN definition and is automatically deployed as soon as bundle is started:
start --> processOrder --> waitForDelivery --> processDelivery --> end
When the service task is executed by the Activiti Engine the execution is delegated to the CamelBehaviour class, which will send a message containing
all process variables to an Activiti endpoint defined in the Camel context.
This behavior is obtained through the use the delegateExpression in the Java service task