Complex Gateways
Introduction
It is important to highlight that, according to BPMN 2.0, the use of a complex gateway in a Process Model is neither necessary nor encouraged. The reason for this is that understanding and interpreting a complex gateway can be difficult, since many actions are hidden from sight through the use of such a gateway.
Furthermore, complex gateways can, in most cases, be replaced by simple types of gateways such as XOR, OR or AND gateways. Using simple types of gateway may mean the model ends up containing more elements and connections than otherwise – but such a model is also generally more understandable at a glance.
However if, for any reasons, you need to use a complex gateway and define your very own split, this document describes how it works.
Example
Let's assume that you want to implement a simple travel booking process. Users are required to select whether they would like to book a plane ticket or a train ticket to their destination. In addition, a hotel stay always needs to be booked, regardless of travel method. While this scenario would usually be modeled using an inclusive OR gateway, you've decided you are going to use a complex gateway.
The model looks follows (no Swimlanes are included to reduce complexity):
You know that you definitely need to split the initial token into two tokens: one for the hotel connection, and one for either plane or train. You can use the 'split' expression to achieve this. The split expression requires an indexed collection of labels (strings) to be the result of the evaluation. That means we could write the following expression:
//Create an empty collection of strings
Indexed String $activatedConnections := NewIndexed(String);
//add the 'plane' or 'train' connection to the collection
$activatedConnections.addElement($meansOfTravel);
//add 'hotel' as a connection to be activated
$activatedConnections.addElement('hotel');
Return $activatedConnections;
The connections in your Process Model need to match the strings you add to the collection returned in the split expression, or you end up with suspended tokens (since the Process Engine wouldn't know where to put the next token).
The Process Engine puts a token on the 'Book hotel' activity, as well as on one of the other two activities ('Book train' or 'Book plane'). There are now two simultaneous parallel activities. These activities will, at some point, be completed by one (or multiple) users. In order to send a confirmation message at the end of the Process, we need to merge these two tokens into one token. Why is this necessary? Because we only want to send one confirmation message, not two. It is therefore important that only one token lands on the 'Send confirmation' activity.
So how should merging take place? Well, remember the AND gateway's merging logic? An AND gateway waits until every incoming connection has a token ready for the merge. The same happens for an inclusive OR gateway as well, except that the OR is capable of back-tracing and then waiting for the right connections to provide a token.
When working with a complex gateway, you are responsible for defining the merging logic yourself. In our small Process, it would be much easier to simply use a merging AND gateway - but keeping on topic, let's use a complex gateway.
For this complex gateway, specify the join expression and leave the split expression empty. The join expression has an implicitly defined variable which can be used in the expression (no declaration necessary). The variable automatically contains the tokens.
The join expression can read the implicitly available variable $workflowTokens (Indexed WorkflowToken). This is the collection of tokens that eventually merge. If you don't specify a split expression, FNZ Studio simply outputs a single token after the merge. So we want to make sure the complex gateway only merges if all tokens have arrived.
We know that there are always two tokens making their way toward this second gateway, so here's how to write the required expression:
If $workflowTokens.size() == 2 Then
Return $workflowTokens;
End
Even if one user now finishes their task much earlier than the other, the first token simply waits on the gateway for merging to take place:
The gateway merges the tokens once the second token arrives, and produces a single token. It is this single token that moves onto the 'Send confirmation' activity. The Process Instance then ends immediately after the execution of this automated task.
Conclusion
To summarize: The logic contained in this Process could be modeled using simpler gateways. It is not necessary to define custom merging logic, but you can do it. Splitting logic is the more likely reason why someone would want to use a complex gateway, but even then it's not common. If you can use simpler gateways, you probably should.