Keep informed?
Subscribe for our newsletter now!

Migrating from jBPM to Activiti

Outdated!

Please note that this blog post is outdated, since we forked Activiti in March 2013 and started a new Open Source BPM project called camunda BPM (www.camunda.org). You will find this topic and loads of more best practices, blueprints etc. there, so you should just have a look 🙂

If you know JBoss jBPM 3 or 4 and have a look at Activiti you may discover that its Java API and process engine features are quite familiar to you. This is due to the fact, that Activiti is the technical successor of the jBPM 3 and 4 development line. It has been developed by the same people and is meant to be a feature-complete replacement for jBPM 3.

Maybe you are looking to modernize your application to leverage powerful process modeling capabilities of BPMN 2.0. Or maybe you want to introduce state of the art Java technologies like CDI, Spring or Java EE 6. Now the question arises of how to migrate your process application from jBPM to Activiti. This blog post briefly sketches different approaches that could be implemented and steps that would need to be performed for such a migration. It is also a continuation of our previous blog post on using BPMN 2.0 with jBPM 3.

Example jBPM 3 Prozess

Process Model

The obvious first step is to migrate the process model from jBPM’s proprietary language called jPDL to BPMN 2.0. Luckily there is the jBPM Migration Tool Project, which can migrate jPDL process definitions from jBPM 3 to BPMN 2.0. It uses XSLT to do the transformation, which is in my opinion the right tool for the job. However, the tool does not cover all features of jBPM and seems a little unfinished. For instance the Mail Node used in the example to the left is completely omitted from the resulting BPMN process. Your mileage may vary.

Due to BPMN 2.0 being technology agnostic, the integration of BPMN 2.0 and Java requires so called vendor extensions in the process definition, which are specific to the particular process engine in use. The jBPM Migration Tool Project has been mainly build for migrations to jBPM 5 (a new engine being build under the jBPM brand) and would therefore generate BPMN 2.0 XML code that is tailored for jBPM 5. Thus, the output of the tool, may need some adjustment to be executable in Activiti. For instance the jBPM 3 example shown here contains an automatic Node called ‘Update CRM’ with an attached Java class:

<node name="Update CRM">
  <event type="node-leave">
    <action name="Update CRM "class="com.camunda.ca002.jbpm.UpdateCustomerDataAction"></action>
  </event>
  <transition to="Problem bearbeiten"></transition>
</node>

The jBPM Migration Tool generated the following BPMN code:

<task drools:taskName="JavaNode" id="Update_CRM" name="Update CRM">
  <ioSpecification>
    <dataInput id="Update_CRM_classInput" name="class" />
    <dataInput id="Update_CRM_methodInput" name="method" />
    <inputSet>
      <dataInputRefs>Update_CRM_classInput</dataInputRefs>
      <dataInputRefs>Update_CRM_methodInput</dataInputRefs>
    </inputSet>
    <outputSet />
  </ioSpecification>
  <dataInputAssociation>
    <targetRef>Update_CRM_classInput</targetRef>
    <assignment>
      <from>com.camunda.ca002.jbpm.UpdateCustomerDataAction</from>
      <to>Update CRM_classInput</to>
    </assignment>
  </dataInputAssociation>
  <dataInputAssociation>
    <targetRef>Update_CRM_methodInput</targetRef>
    <assignment>
      <from>execute</from>
      <to>Update CRM_methodInput</to>
    </assignment>
  </dataInputAssociation>
</task>
<sequenceFlow id="flow_Update_CRM1" sourceRef="Update_CRM" targetRef="Problem_bearbeiten" />

Activiti would just require:

<serviceTask activiti:class="com.camunda.ca002.jbpm.UpdateCustomerDataAction" id="Update_CRM" name="Update CRM" />
<sequenceFlow sourceRef="Update_CRM" targetRef="Problem_bearbeiten" />

This may look like a huge difference in the code, but it turns out that its quite easy to make these adjustments using BPMN modeling tool. In the example above, you just change the Task’s type to Service Task and add the activiti:class attribute. The jBPM 5 extensions will be ignored by Activiti anyway. However, if larger quantities of process definitions are to be migrated, you could also extend the jBPM Migration Tool Project to directly produce BPMN for Activiti. Due to the more compact XML that Activiti consumes, the extension is more about removing lots of unnecessary things from the mapping than adding totally new things.

Graphical Layout

During my tests the tool was not able to migrate the graphical layout of the example process model. But even if it would, it remains questionable if such a migration is useful, because jPDL is typically modeled top-down whereas BPMN best practice is to model from left to right. That means you would need to rearrange all model elements anyway. The automatic layouting that some BPMN modeling tools provide could help to reduce the effort, but is also no silver bullet, because auto-layouted processes usually require some manual rearrangement, too. Furthermore, experience has shown that jPDL models tend to be rather technical and not easy to understand for the business. So instead of just migrating the technical process model to another language, you should also consider a redesign of the process to more clearly express the business side of things.

Ways INTO and OUT OF the process engine

Java Code

Ok, that was the easy part. Lets now have a look on how a Java-based process application is wired with the process engine that it is using. In general, one needs ways INTO a process engine and ways OUT OF it.

The ways INTO the engine are typically provided as a Java API that allows to, e.g., start process instances, query task lists or complete a task. If you compare the API of jBPM 3 or 4 and Activiti you will find a lot of similarities, although jBPM 3 has a more object-oriented API than jBPM 4 and Activiti, which are service-oriented. Nevertheless, client code that invokes these API services needs to be modified to call the correct methods of Activiti’s API services. The conceptional similarities between jBPM 3 or 4 and Activiti make the mapping API calls very easy, because in most cases it will be a simple one to one mapping.

For instance the JUnit test of the example process shown above uses:

public class TestTicketProcess extends TestCase {
  public void testProcessWithKnownCustomer() {

    ProcessDefinition def = ProcessDefinition.parseXmlInputStream(
      this.getClass().getResourceAsStream("/TicketProcess/processdefinition.xml"));

    ProcessInstance pi = def.createProcessInstance();

    pi.getContextInstance().createVariable("email", "bernd.ruecker@camunda.com");
    pi.getContextInstance().createVariable("problemDescription", "Test");

    pi.signal();
  }
}

In Activiti it would look like this:

public class TestTicketProcess extends ActivitiTestCase {

  @Deployment(resources = "/TicketProcess/processdefinition.xml")
  public void testProcessWithKnownCustomer() {
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("TicketProcess");

    runtimeService.setVariable(pi.getId(), "email", "bernd.ruecker@camunda.com");
    runtimeService.setVariable(pi.getId(), "problemDescription", "Test");

    runtimeService.signal(pi.getId());
  }
}

The jBPM Migration Tool Project also outlined some plans for a scanner, the finds uses of the jBPM 3 API in your Java code, but it seems that there is no implementation of that yet. But in the end it is just refactoring. Your favorite Java IDE will assist you in that: You just remove the jBPM libraries from the classpath and fix all the compiler errors that appear by changing the code to use Activiti’s API. Alternatively, you may also think about using a wrapper for the API of the process engine, if you anticipate future migrations and want to abstract from the process engine.

The ways OUT OF the jBPM 3 engine are Action Handlers:

public class UpdateCustomerDataAction implements ActionHandler {

  public void execute(ExecutionContext ctx) throws Exception {
    CrmService crm = CrmServiceBean.getCrmService();

    Customer customer = (Customer) ctx. digetVariable("customer");
    String newAccountManager = (String) ctx.getVariable("newAccountManager");
    customer.setAccountManager(newAccountManager);

    crm.updateCustomer(customer);

    ctx.getContextInstance().deleteVariable("newAccountManager");
  }
}

Activiti has a similar concept called Java Delegate:

public class UpdateCustomerDataAction implements JavaDelegate {

  public void execute(DelegateExecution ctx) throws Exception {
    CrmService crm = CrmServiceBean.getCrmService();

    Customer customer = (Customer) ctx.getVariable("customer");
    String newAccountManager = (String) ctx.getVariable("newAccountManager");
    customer.setAccountManager(newAccountManager);

    crm.updateCustomer(customer);

    ctx.removeVariable("newAccountManager");
  }
}

Can you spot the differences? 😉

This is again just refactoring and can be done using a Java IDE or maybe just grep and sed. If you have lots of ActionHandlers and don’t want to refactor all of them, a simple adapter class could make them directly usable in Activiti, because the ActionHandler interface of jBPM3 is quite similar to Activiti’s JavaDelegate. Given such an ActionHandlerAdapterDelegate, the XSL transformation that produces the BPMN 2.0 XML could be modified directly introduce the adapter class and provide it the ActionHandler class name via Field Injection.

Executing jPDL on the PVM

If you are ready to change your client code, but not willing to touch your jPDL process definitions because you really have a lot of them, there is another more esoteric approach: The core of the Activiti process engine is a so called Process Virtual Machine (PVM), which can actually execute different process languages. BPMN 2.0 is just one possible language that we implemented on top the PVM. However, it would be possible to implement jPDL as a PVM language so that Activiti could natively execute processes from jBPM 3 or 4. This way one could leverage new features introduced by Activiti, e.g., the use of CDI or Spring beans in process definitions, the improved history system or even the Process Diagram API. Also new tools available for Activiti like camunda fox cockpit could be reused for legacy jBPM processes. But as I said, this is a rather esoteric approach, which I only mentioned for completeness. The effort for such an implementation is nearly as high as building a process engine from scratch, which is a bad idea, too.

Runtime Data

So far I discussed the design time artifacts of a process automation project. But what about the runtime data: The deployed process definitions and more importantly the running process instances? Well, the database design of Activiti is quite similar to that of jBPM 4, but has of course evolved since then. jBPM 3 differs substantially from Activiti in terms of its database schema. Besides that, there can also be cases where conceptual differences make the data completely different and maybe not mappable at all. Thus, migrating running instances to another engine is a lot of effort and especially requires good knowledge of the two engines as well as a lot of testing. It needs good arguments to justify such an investment, e.g., large quantities of long running process instances.

Consequently most migration projects do not aim for instance migration and instead use alternative approaches to retire the old process engine. One option is to run jBPM and Activiti in parallel during a transition period and leave existing processes running in jBPM whereas new ones would be created in Activiti. Once all the old process instances have reach their end, you can shut down jBPM and maybe archive its data. Another option is to stop jBPM process instances at well defined points like user tasks or other wait states and then start a new process instance in Activiti at the same point and with the same process variables. In future, camunda fox may even get a migration API to support such an approach.

Don’t just Migrate. Redesign!

Now that you have seen the different options for migration, it has probably also become clear that there is no trivial way of doing it. Furthermore, executing the exact same processes on a different engine supporting BPMN 2.0 is not an end in itself. So when you invest into modernizing your processes, you should not only improve on the technical level, but also try to generate some new value on the business level by redesigning the process application to provide new features and improvements. Since you have already gained experience with using a process engine, you now have the unique chance to do everything right from the beginning. If you need help in any of these areas, we are available to assist you.

What about camunda fox?

The process engine inside the camunda fox BPM Platform is a stabilized version of Activiti, for which camunda provides enterprise support and advanced tooling. Thus, the migration steps I described here will work just fine with it. Grab the Community Edition and see for yourself!

Already read?

Scientific performance benchmark of open source BPMN engines

Why BPMN is not enough

Decision Model and Notation (DMN) – the new Business Rules Standard. An introduction by example.

New Whitepaper: The Zero-Code BPM Myth

Leave a reply