Friday, December 28, 2012

Activiti Designer 5.11.0 released

Activiti Designer 5.11.0 is released today. You can install the plugin via the http://activiti.org/designer/update repository or download the package from the http://activiti.org/designer/archived site. You can also find the plugin jars in our Maven repository https://maven.alfresco.com/nexus/content/repositories/activiti-releases/org/activiti/designer/

This release includes a big refactoring of the BPMN parsing and export logic and the underlying BPMN POJO model. Since we have the activiti-bpmn-model and activiti-bpmn-converter projects in the Activiti project we now have one foundation for parsing for the Activiti Engine, Modeler and Designer. The Modeler and Designer in addition also use the BPMN XML export logic.

In addition to this refactoring the 5.11.0 release also contains a couple of new features (message boundary events, made custom service tasks a first class citizen so you can add execution listeners and other service task functionality), and some bug fixes.

Because the foundation of the Designer is now replaced with the Activiti BPMN model and converter projects we are very eager to have you test this version and report any bugs found in our JIRA. Hope you'll enjoy using this new release.

Friday, December 7, 2012

Implement parallel execution in Activiti

Running service tasks in parallel in Activiti is an area where we've seen a lot of confusion. In this article I want to show you how this works using the parallel gateway and alternatively how you can do this using the Activiti / Apache Camel integration.

Let's consider a very simple process using the parallel gateway.











When we don't specify any additional attribute to the parallel tasks in this simple process definition Activiti will first execute Parallel task 1 (let's assume that one is defined first in the BPMN XML), and after that task has been completed it will execute Parallel task 2. So although we are using the parallel gateway the service tasks are executed in sequence. This is to prevent issues with variable updates and troublesome thread syncing logic.

But if we really want to execute the service tasks in parallel there are other possibilities. The first one is to define both tasks as asynchronous tasks using the Activiti async attribute. Now the parallel tasks are initiated via the job executor and will really run in parallel. Well you might think that.  Actually, they are again run in sequence because we've built-in the concept of exclusive jobs in the Activiti Engine (see the Activiti userguide). This will by default prevent jobs of the same process instance to run at the same time. So by default jobs of the same process instance will run in sequence.

What we can do is disable the exclusive jobs feature by adding an activiti:exclusive="false" attribute to both parallel tasks in our example process. This will run both asynchronous parallel tasks together and finally we have our parallel execution behavior. But....  now we'll run into the following error message:

ExecutionEntity[4] was updated by another transaction concurrently

Because both service tasks run in parallel they both trigger the same parallel join logic, but in a different transaction. And because both service tasks can complete around the same time, they both will try to execute the parallel gateway join logic. And this will throw an optimistic locking exception.

But luckily there's a good solution to this problem. When we'll use the Apache Camel integration we can use the queuing logic of Apache Camel to create the parallel execution behavior for us. First we have to adapt our simple process definition a bit.










As you can see there's now a receive task following both parallel tasks. With the following service task definition we can invoke a Camel context from a service task:

<serviceTask id="serviceTaskAsync1" activiti:delegateExpression="${camel}"/>

Of course we need to define the camel Spring bean in the Engine configuration so it can find it. We can do that according to the following configuration:

<camelContext id="camelProcess" xmlns="http://camel.apache.org/schema/spring">
  <packageScan>
    <package>org.activiti.camel.route</package>
  </packageScan>

</camelContext>

<bean id="camel" class="org.activiti.camel.CamelBehaviour">
  <constructor-arg index="0">
    <list>
      <bean class="org.activiti.camel.SimpleContextProvider">
        <constructor-arg index="0" value="asyncCamelProcess"/>
        <constructor-arg index="1" ref="camelProcess"/>
      </bean>
    </list>
  </constructor-arg>

</bean>

The camel Spring bean defines an implementation of the ActivityBehavior interface and connects the Camel context (camelProcess) to the process definition key (asyncCamelProcess). Now what's left is the definition of the Camel route that's read by the Camel context by scanning the org.activiti.camel.route package.

public class AsyncCamelRoute extends RouteBuilder {
 

 @Override
 public void configure() throws Exception {
  

  from("activiti:asyncCamelProcess:serviceTask1?copyVariablesToProperties=true")
    .setHeader("destination", constant("activiti:asyncCamelProcess:receive1"))
    .to("seda:asyncQueue");

  from("seda:asyncQueue")
    .to("bean:sleepBean?method=sleep")
    .to("seda:receiveQueue");
   
  from("activiti:asyncCamelProcess:serviceTask2?copyVariablesToProperties=true")

    .setHeader("destination", constant("activiti:asyncCamelProcess:receive2"))
    .to("seda:asyncQueue2");
  

  from("seda:asyncQueue2")
    .to("bean:sleepBean?method=sleep")
    .to("seda:receiveQueue");

  from("seda:receiveQueue").recipientList(header("destination"));
 }
}


This might seem a bit complex at first sight, but when you take some time to read it it's actually quite simple. The first route definition defines that from the first parallel service task we copy all process variables to the Camel message properties and sent it to the in-memory asyncQueue using the Camel SEDA connector. And we define a header that sets the destination property to the receive1 task reference.

We do the same for the second parallel service task and change the queue to asyncQueue2 and set the destination to receive2 task. Then in the third route the messages from the asyncQueue are sent to a Java bean (in specific to the sleep method) and the result object of that method is sent to the receiveQueue.

The recipientList invocation tells Camel to sent a message receive on the receiveQueue to the value in the destination header property. Because the SEDA connector by default processes 1 message at a time we are sure that the signaling of the receive1 and receive2 tasks are always done in sequence and we are sure that we don't run into optimistic locking exceptions.

So by using Activiti together with Camel we can implement real parallel execution in a safe manner without the need to write a lot of code.  If you want to test a bit with this example yourself you can checkout the activiti-camel module in our Github repository and execute the AsyncProcessTest in that project.

Hope this has provided some more insight into the use of the parallel gateway and parallel execution in the Activiti Engine.

Wednesday, December 5, 2012

Activiti 5.11 released

Activiti 5.11 has been released today (5 december 2012). This release contains a lot of new features and a lot of bug fixes. Be sure to watch new blog posts from the Activiti team in the coming weeks as we'll blog about these new features. The main highlights of the 5.11 release are:

  • Added Activiti Modeler to the Activiti Explorer web application
  • Removed buggy demo script and replaced with simpler distribution
  • Support for doing queries that are not out-of-the-box possible with the query api (called 'native queries')
  • Enhanced ability to query for history variable values
  • Improved functionality to suspend and activate process definitions and instances
  • Improved Activiti QA and added DB2 and MSSQL servers
  • Added support for using a service call in a Java delegate (see here for more details)
  • Lots of bug fixes
Grab the 5.11 distribution from the Activiti download page. Note that we removed the demo script and just provide the Explorer and REST web applications as WAR files in the distribution. In addition, the database scripts are now also part of the distribution in the database folder.

We hope you enjoy the new Activiti 5.11 release! The Designer 5.11 release we'll follow in a couple of weeks.

The Activiti team