Normally, a node is always executed after a token has entered the node. So the node is executed in the thread of the client. We'll explore asynchronous continuations by looking two examples. The first example is a part of a process with 3 nodes. Node 'a' is a wait state, node 'b' is an automated step and node 'c' is again a wait state. This process does not contain any asynchronous behaviour and it is represented in the picture below.
The first frame, shows the starting situation. The token points to node 'a', meaning that the path of execution is waiting for an external trigger. That trigger must be given by sending a signal to the token. When the signal arrives, the token will be passed from node 'a' over the transition to node 'b'. After the token arrived in node 'b', node 'b' is executed. Recall that node 'b' is an automated step that does not behave as a wait state (e.g. sending an email). So the second frame is a snapshot taken when node 'b' is being executed. Since node 'b' is an automated step in the process, the execute of node 'b' will include the propagation of the token over the transition to node 'c'. Node 'c' is a wait state so the third frame shows the final situation after the signal method returns.
While persistence is not mandatory in jBPM, the most common scenario is that a signal
is called within a transaction. Let's have a look at the updates of that transaction.
First of all, the token is updated to point to node 'c'. These updates are generated by
hibernate as a result of the GraphSession.saveProcessInstance
on a
JDBC connection. Second, in case the automated action would access and update some
transactional resources, those transactional updates should be combined or part of
the same transaction.
Now, we are going to look at the second example, the second example is a variant of
the first example and introduces an asynchronous continuation in node 'b'. Nodes 'a' and
'c' behave the same as in the first example, namely they behave as wait states. In jPDL,
a node is marked as asynchronous by setting the attribute async="true"
.
The result of adding async="true"
to node 'b' is that the process
execution will be split up into 2 parts. The first part will execute the process up to
the point where node 'b' is to be executed. The second part will execute node 'b' and
that execution will stop in wait state 'c'.
The transaction will hence be split up into 2 separate transactions. One transaction
for each part. While it requires an external trigger (the invocation of the
Token.signal
method) to leave node 'a' in the first transaction, jBPM
will automatically trigger and perform the second transaction.
For actions, the principle is similar. Actions that are marked with the
attribute async="true"
are executed outside of the thread that
executes the process. If persistence is configured (it is by default), the actions
will be executed in a separate transaction.
In jBPM, asynchronous continuations are realized by using an asynchronous messaging system. When the process execution arrives at a point that should be executed asynchronously, jBPM will suspend the execution, produces a command message and send it to the command executor. The command executor is a separate component that, upon receipt of a message, will resume the execution of the process where it got suspended.
jBPM can be configured to use a JMS provider or its built-in asynchronous messaging system. The built-in messaging system is quite limited in functionality, but allowes this feature to be supported on environments where JMS is unavailable.