Transaction demarcation

As explained in the section called “Graph execution” and ???, jBPM runs the process in the thread of the client and is by nature synchronous. Meaning that the token.signal() or taskInstance.end() will only return when the process has entered a new wait state.

The jPDL feature that we describe here from a modelling perspective is Chapter 13, Asynchronous continuations.

In most situations this is the most straightforward approach because the process execution can easily be bound to server side transactions: the process moves from one state to the next in one transaction.

In some scenarios where in-process calculations take a lot of time, this behaviour might be undesirable. To cope with this, jBPM includes an asynchronous messaging system that allows to continue a process in an asynchronous manner. Of course, in a java enterprise environment, jBPM can be configured to use a JMS message broker instead of the built in messaging system.

In any node, jPDL supports the attribute async="true". Asynchronous nodes will not be executed in the thread of the client. Instead, a message is sent over the asynschronous messaging system and the thread is returned to the client (meaning that the token.signal() or taskInstance.end() will return).

Note that the jbpm client code can now commit the transaction. The sending of the message should be done in the same transaction as the process updates. So the net result of the transaction is that the token has moved to the next node (which has not yet been executed) and a org.jbpm.command.ExecuteNodeCommand-message has been sent on the asynchronous messaging system to the jBPM Command Executor.

The jBPM Command Executor reads commands from the queue and executes them. In the case of the org.jbpm.command.ExecuteNodeCommand, the process will be continued with executing the node. Each command is executed in a separate transaction.

So in order for asynchronous processes to continue, a jBPM Command Executor needs to be running. The simplest way to do that is to configure the CommandExecutionServlet in your web application. Alternatively, you should make sure that the CommandExecutor thread is up and running in any other way.

As a process modeller, you should not really be concerned with all this asynchronous messaging. The main point to remember is transaction demarcation: By default jBPM will operate in the transaction of the client, doing the whole calculation until the process enters a wait state. Use async="true" to demarcate a transaction in the process.

Let's look at an example:

...
<start-state>
  <transition to="one" />
</start-state>
<node async="true" name="one">
  <action class="com...MyAutomaticAction" />
  <transition to="two" />
</node>
<node async="true" name="two">
  <action class="com...MyAutomaticAction" />
  <transition to="three" />
</node>
<node async="true" name="three">
  <action class="com...MyAutomaticAction" />
  <transition to="end" />
</node>
<end-state name="end" />
...

Client code to interact with process executions (starting and resuming) is exactly the same as with normal (synchronous) processes:

...start a transaction...
JbpmContext jbpmContext = jbpmConfiguration.createContext();
try {
  ProcessInstance processInstance = jbpmContext.newProcessInstance("my async process");
  processInstance.signal();
  jbpmContext.save(processInstance);
} finally {
  jbpmContext.close();
}

After this first transaction, the root token of the process instance will point to node one and a ExecuteNodeCommandmessage will have been sent to the command executor.

In a subsequent transaction, the command executor will read the message from the queue and execute node one. The action can decide to propagate the execution or enter a wait state. If the action decides to propagate the execution, the transaction will be ended when the execution arrives at node two. And so on, and so on...