The complex gateway is one of the least used features in BPMN, yet there are some very specific use cases where it offers the perfect solution. One of these cases is something I ran into when designing a process in Oracle Integration Cloud at a client recently. This article will describe what this use case entailed, looking back at how the complex gateway worked before in Oracle BPM 12c and what I believe is the best workaround to implement in OIC.
A quick little history lesson. As a BPMN default, when defining a parallel or inclusive flow, all the flows/tokens need to be completed before the process can move on. The process will wait for these flows at the merge gateway, which by default is defined as the same type as the split gateway. So a parallel split would mean a parallel merge, an inclusive split an inclusive merge, and so on. In Oracle BPM 12c you could use a complex gateway to circumvent this behavior by change the merge gateway and defining an exit criterium, a simple true or false condition, and abort any pending flows when this criterium was met (as shown in the examples below).
However, for some reason Oracle has decided not to make this option available (yet) in OIC which means that any parallel or inclusive flows you define will need to complete all their active flows one way or another. Let’s illustrate the problem this causes with a simple example.
Imagine a scenario where at some point in the process a decision needs to be made either by a user or some sort of system check, and whichever comes first will be the deciding factor. In the figure below, this scenario is illustrated as a simple process. After the process is started, two things will happen: one flow will wait for a message from another system, while the other will wait for user input through a task. However, since this is a parallel gateway with a parallel gateway merge, both flows will need to be completed before the process can move on, which is not what you want in this scenario. A complex merge gateway would allow you to abort the second flow after the first one completes, regardless of which one comes first.
Let’s move on from that simple example to the actual use case. The figure below depicts a real-life process I had to implement at the client. At first glance it looks a little bit complex (and already includes the workaround) so I’ll try to break it down into pieces. The way the flow works, starting from the parallel gateway:
The way the flow completes:
However, because there is no complex gateway with an exit condition to abort any remaining open flows, this was initially implemented as a parallel merge meaning all flows will need to be completed. So once the main flow/human task completes, it must send a signal to the event-based gateway of the optional flow that it is no longer needed (depicted in the figure below by the arrow). A rather ugly solution for this problem but it does work.
Another way to solve this issue is by getting rid of the parallel flow all together and creating a separate process for the optional flow, to sort of decouple the dependency. Key difference here is that the responsibility for completion gets turned around. Once the main flow completes, it will check whether the human task of the optional flow is still active. If it is, it will wait in the ‘Message Catch’ for a signal from the optional flow once it completes (as depicted by the arrow in the figure below). This completely circumvents the need for a complex gateway but creates a bit more overhead in terms of the new process.
Ultimately, both workarounds have some advantages and disadvantages. Trying to solve the issue in one process with a parallel (or possible inclusive) gateway will keep all your related business logic together. It does create a rather ugly process with a lot of unnecessary components that could be slightly difficult to interpret for a future developer. On the other hand, splitting the process into two will separate your business logic but maintain some order and cleanliness in your processes which makes them much easier to understand and maintain.
After also discussing this with our architects we decided to go with the second option. It’s a lot cleaner and more robust, and both processes can be modified independently without impacting the mechanism for completion. Hopefully Oracle will introduce the complex gateway in OIC soon as it is an integral, albeit niche, piece of functionality and it would certainly help with modelling these kinds of common situations.