Sunday, October 17, 2010

BPMN 2.0 with Activiti - book order tutorial (2)

Step 2 - Adding a start form to the process

In a small series of posts we will show how to get started with Activiti BPMS by getting a simple book order process running on Activiti Engine. All the BPMN 2.0 constructs that the Activiti Engine currently supports will be addressed in the coming few weeks.

In the process model below you can see the Java Service Task that was implemented in the previous post. That time the 'bookTitle' variable was set from within a unit test, today we will add a start form to the process which lets a user fill in a book title in the Activiti Explorer.

Before we start working with eclipse, to define the process and the form, install Activiti. In this example the beta 2 release of Activiti is used. Download it and unzip the file in a directory. Check out the user guide for more information, but for now it is enough to run the ant demo.setup task to get the engine running. When ant is all done a Tomcat distribution is downloaded and started and the Activiti apps are installed.

With Tomcat running silently in the background it is time to open eclipse. Since the BPMN 2.0 spec does not specify how task forms should be rendered, forms are defined in the bpmn xml file using Activiti specific constructs. The xml below shows how to add the bookorder.form to the start event in the book order process.
<process id="bookorder">
<startEvent id="theStart" activiti:form="bookorder.form"/>
<sequenceFlow id="flow1" sourceRef="theStart"
targetRef="checkAvailability" />
<serviceTask id="checkAvailability"
name="Availability Check"
activiti:class="org.bpmnwithactiviti.CheckAvailability" />
<sequenceFlow id="flow2" sourceRef="checkAvailability"
targetRef="waitState" />
<receiveTask id="waitState" />
<sequenceFlow id="flow3" sourceRef="waitState"
targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
The task forms that can be rendered by the Activiti Explorer are just plain html files. By convention they have the .form extension. The form that we are going to use is very simple and just has an inputfield to enter the title of the book that we want to order. The variable in the form, in this case the 'bookTitle' variable, will be stored as process variables after completion of the task. The variables must be camel-cased. Currently supported are String, Integer, Boolean and Date, String is the default type.
<h1>Book Order</h1>
<table>
<tr>
<td>
<label>Book title:
<input type="text" name="bookTitle" value="" />
<input type="hidden" name="bookTitle_required" value="true" />
<input type="hidden" name="bookTitle_type" value="String" />
</label>
</td>
</tr>
</table>
Now that the form and the bpmn xml is ready we can package these files in a business archive, the deployable unit on Activiti Engine. This you can do by exporting the eclipse project with the jar file export wizard. Select only the bpmn xml file and the form and name the file bookorder.bar. To deploy the archive we will create a simple J2SE class with a main method.
public class BarDeployer {
public static void main(String[] args) throws Exception {
ProcessEngine processEngine = new ProcessEngineBuilder()
.configureFromPropertiesResource("activiti.properties")
.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
String barFileName = "bookorder.bar";
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName));
repositoryService.createDeployment().name(barFileName)
.addZipInputStream(inputStream).deploy();
}
}
Note that we now use a different activities.properties file to build the process engine. Since deployment will take place on the Activiti Engine installation running on Tomcat a different config is needed than the one used in our previous unit test.

Now that the bar file is deployed you can see the installed bookorder process with Activiti Explorer on http://localhost:8080/activiti-explorer/. Login as kermit with password kermit and take a look at the processes he can start. On the top of the list you see the Book Order process.

Before you can start the process you need to deploy a jar file that contains the CheckAvailability class file in the Tomcat lib directory and restart Tomcat, otherwise the engine can't find the class that implements the Java Service Task we build in the previous post.

Note that the Action behind the Book Order process is not 'Start Process' but 'Start Form'. Only when we have put in a book title in the form and pressed the 'Ok' button a process instance is created and the 'bookTitle' variable is set.

When you submit the form you can see some logging appearing in de Tomcat log file telling you whether the book is available or not. The code of the BookOrder project, including the bar and jar file, can be checked out from the Google Code repository.

That was it for now, next time we will take a look at gateways!

BPMN 2.0 with Activiti - book order tutorial

Step 1 - Implementing a Java Service Task

In a small series of posts we will show how to get started with
Activiti BPMS by getting a simple book order process running on Activiti Engine. All the BPMN 2.0 constructs that the Activiti Engine currently supports will be addressed in the coming few weeks. Today an easy start with the Java Service Task.

Let's first take a look at the simple version of the bookorder process modeled with the Activiti Modeler tool:

After filling out the title of a book in an order form with Activiti Explorer a process instance is created. Then a Java Service Task checks if the ordered book is available and depending on the outcome of that check the process routes the order, via an exclusive gateway, to a Groovy Script Task to start the shipping process or, when the book turns out to be unavailable, a User Task is created to cancel the order.

Lets take a look at the Java Service Task. We will use this task to implement the availability check in our process. The Activiti Engine executes a Java Service task by calling the execute method on a class that implements the ActivitiBehaviour interface. The CheckAvailability class below does this by extending the BPMNDelegation convenience class from the Activiti API. In the code you can see that an ActivityBehavior instance has access to the current state of the process through the ActivityExecution that is passed in as a parameter of the execute method.
public class CheckAvailability extends BpmnJavaDelegation {

public void execute(DelegateExecution execution) {
String bookTitle = (String) execution.getVariable("bookTitle");
boolean bookAvailable = false;
if (bookTitle.equalsIgnoreCase("BPMN 2.0 with Activiti")) {
bookAvailable = true;
}
execution.setVariable("bookAvailable", bookAvailable);
}
}
The execute method takes a process variable from the execution, checks its value and depending on the outcome it sets another variable, called bookAvailable, on the execution. Let's test this with a simple BPMN 2.0 process in eclipse. Take a look at the process below.

<process id="bookorder">
<startEvent id="theStart"/>
<sequenceFlow id="flow1" sourceRef="theStart"
targetRef="checkAvailability" />
<serviceTask id="checkAvailability" name="Availability Check"
activiti:class="org.bpmnwithactiviti.CheckAvailability" />
<sequenceFlow id="flow2" sourceRef="checkAvailability"
targetRef="waitState" />
<receiveTask id="waitState" />
<sequenceFlow id="flow3" sourceRef="waitState" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
Right after the process will be started the engine reaches the CheckAvailability servicetask, which is implemented by the CheckAvailability class. After execution of the task the engine moves on to the waitstate. There the engine will give control away, waiting to be signalled by the outside world to move on. We will see later how we can signal a process with for example a user task, for now this task is only there so we can test the values of the 'bookAvailable' variable. Without the waitstate activity the process would end after execution of the service task and there would be no process to check the variables of to perform the test.

The ActivitiRule, a convenience class for ProcessEngine and services initialization in the form of a JUnit rule, is used to setup the engine with the activiti-mem.properties file. It will configure the engine with an in-memory H2 database so we can test locally in our eclipse environment. From the ActivitiRule the RuntimeService is retrieved to create an instance of the bookorder process that is deployed thanks to the @Deployment annotation. Later the bookTitle is set after an order form is completed, but in this test we will start the process with a processVariables map containing the booktitle.

public class JavaServiceTaskTest {

@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti-mem.properties");

@Test
@Deployment(resources={"bookorder.javaservicetask.bpmn20.xml"})
public void bookAvalaible() {
Map processVariables = new HashMap();
processVariables.put("bookTitle", "BPMN 2.0 with Activiti");
ProcessInstance pi = activitiRule.getRuntimeService()
.startProcessInstanceByKey("bookorder", processVariables);
processVariables = activitiRule.getRuntimeService()
.getVariables(pi.getId());
assertEquals(true, processVariables.get("bookAvailable"));
}
}

That is all there is to it. In the next part we will add a form to the process to be able to enter a book title. After the form is added our enhanced process will be packaged in a bar file and deployed to an Activiti Engine instance running on Tomcat so we can start the process from the Activiti Explorer tool.

That is it for now. The code of the BookOrder project can be checked out from the Google Code repository. There are more usage examples of the Java Service Task there showing how to inject fields in the CheckAvailability class and how to use expression in BPMN to inject these fields dynamically.

Saturday, October 2, 2010

Mule 3 released

It maybe a bit strange to start of this blog with a post about Mule, but the release of version 3.0 of the Mule community edition is certainly a valid reason.

It's been a while since I wrote the book Open-source ESBs in Action with Jos Dirksen. But the coverage of Mule in that book was based on Mule 2.x, which was the current version until a few weeks. In the last couple of years other open source integration frameworks like Apache Camel and Spring Integration came along and provided similar functionality. With version 3.0 Mule steps up again and provides great additional functionality with foremost the following features: hot deployment, new flow based architecture, annotation support and better support for web services and rest.

I want to highlight two features of Mule 3.0 in this post, which are the new flow based architecture and hot deployment. Previous versions of Mule had a service based architecture to implement your integration logic. The following picture taken from the Mule userguide describes it in a very easy manner.

As the picture shows, integration logic was implemented via an inbound router to process incoming messages, via a service component to implement additional processing logic, and an outbound router for sending the message along the path. In XML this looked liked the following snippet:

<service name="hello">
  <inbound>
    <jms:inbound-endpoint queue="hello.in"/>
  </inbound>
  <component class="org.mule.TestComponent"/>
  <outbound>
    <pass-through-router>
      <jms:outbound-endpoint queue="hello.out"/>
    </pass-through-router>
  </outbound>
</service>

Nothing wrong with this kind of architecture, but it becomes a bit tricky when you have to specify all kinds of transfers, multiple component classes etc. The new flow based architecture solves these issues and provides a very clean and flexible architecture based on message processors and sources to implement your integration logic (see the following figure taken from the userguide).

All the things you want to do with a message after it has arrived at a message source is implemented with message processors. So transformers, routers and custom logic are all message processors. This makes it very clean and easier to understand. The new flow based architecture looks like this in XML:

<flow name="hello">
  <jms:inbound-endpoint queue="hello.in"/>
  <component class="org.mule.TestComponent"/>
  <jms:outbound-endpoint queue="hello.out"/>
</flow>

This looks very simple doesn't it? For a very small example like I've implemented here, the differences are not huge of course. But you can imagine that for more complex examples, the new flow based architecture makes your life a lot easier.

The other huge improvement in Mule 3.0 is hot deployment. One of the main differences between Apache ServiceMix and Mule when we wrote the Open-source ESBs in Action book was a hot deployment feature from an enterprise perspective. And now with version 3.0 it's there and looks very promissing. In the apps directory of the Mule installation you can now deploy a Mule configuration and JARs (if necessary) and Mule picks it up automatically. Then, if you want to change the Mule configuration you can simply update the file and again Mule picks it up automatically. For more information you can look at the userguide. Hot deployment now works for a lot of implementations, but there is still some room for improvement. For example, only the main Mule configuration file is monitored by Mule, not its child Mule configurations. When compared to other open source ESBs like Apache ServiceMix and Open ESB, I see that Mule takes a web application like approach to hot deployment, where the others use OSGi.

So to summarize, version 3.0 is certainly a step forward! It provides a lot of improvements and some great new features including the discussed hot deployment and the new flow based architecture. And from a perspective of the open source BPM Activiti project I'm enthousiastic about the possibilities of integration between Mule and Activiti. So I hope to see Activiti integration in the next 3.x version of Mule.