Using Zeebe’s workflows instead of Sagas in Axon

George
The Startup
Published in
4 min readOct 20, 2019

--

Snapshot from Zeebe’s Simple Monitor showing Trip Booking workflow instance

Implementing Microservices and Event Driven Architecture can be very tricky. One of the most difficult parts is finding the way to integrate all these asynchronous messages in one coherent and understandable business process. In the real world business processes tend to be long-running, so they need to be stateful and they need to be persistent. This has long since been solved in the world of traditional monolithic applications by using a workflow engine, preferably based on ubiquitous BPMN standard.

In the world of EDA and Microservices, things are a bit different. The established practice is to implement a Saga pattern. Here is how it is done in Axon, for example. The problem is that, often the sequence of events in a Saga is not clearly understandable, let alone visualizable.

There is an excellent article by Bernd Rücker making a very convincing case about the place of BPMN-enabled workflow engine in the orchestration of microservices involved in a complicated and long-running business process.

So what if we try to combine two very excellent frameworks: Axon for event-driven microservices (all the plumbing for distributing commands and events, CQRS, etc.) and Zeebe — Camunda’s workflow engine for microservices orchestration based on BPMN.

Bridging Axon and Zeebe for long-running business process logic

In this post I’ll walk you through an example integration of Zeebe with Axon. All the code is available from this GitHub repository. I assume the reader is familiar with Axon framework and Zeebe.

First thing to decide is what kind of integration we are attempting. We have two main choices here:

  • In a typical Axon Saga, send a message to start a workflow instance in Zeebe and wait for a workflow to complete (listening for a workflow completion event). In this scenario, Axon’s Saga or aggregate are offloading the whole of workflow processing logic to Zeebe.
  • Replace Axon’s Saga completely, dispatching all relevant events from API controller (or other event-handling components and aggregates) to Zeebe’s workflow instance and delegating all jobs processing steps to the Axon’s aggregate via proper commands dispatching.

Here we shall look at how we can implement integration of the second type here, i.e. Axon’s aggregate will be used to do all the actual work, whereas Zeebe will be used for modeling, tracking and visualizing the state of the workflow. I believe this way we are leveraging the best of two worlds: Axon’s tight integration with CQRS and DDD techniques and Zeebe’s BPMN formalization and workflow visualization.

Here is a schematic representation of the way Axon could be integrated with Zeebe. The key is to use exclusive gateways to guard every service task in the workflow, waiting for Axon’s event handler to send appropriate messages effectively deciding which path the workflow instance must proceed. The event handler is also a Zeebe worker subscribing to each service task. The actual job processing is then delegated to the Axon’s aggregate.

Axon — Zeebe integration schema

The main points here are:

  • 1. API controller uses Axon’s command gateway instance to communicate commands to the aggregate (as usual) but also it uses an instance of event gateway to publish a special type of events (let’s call them “workflow” events). WorkflowEvent can simply be an ad hoc implementation of an interface specifying the proper message name and correlation value to be transmitted to Zeebe. Here is how a workflow event can be created.
Workflow event implementation: references a particular message name and a correlation value
  • 2. Event handler is a Spring component listening for any Axon events, including any workflow events. Here is the declaration of one such event listener.
Axon’s component listening to workflow events, forwards messages to Zeebe
  • 3. Event handler simply forwards any workflow event it receives to the Zeebe workflow engine using the auto-wired zeebeClient . The message the event contains all the necessary information needed to construct a valid message to Zeebe: message name, correlation key and correlation value.
Sending messages to Zeebe
  • 4. Once the message gateway receives a message with the matching name and correlation value it allows the workflow to proceed to the service task state. The Axon’s event handler subscribes to all the jobs of the workflow using methods annotated with ZeebeWorker annotation. It then
Subscribing to Zeebe’s jobs
  • 5. Event handler dispatches appropriate commands to the command gateway to be processed by the aggregate.
Dispatching commands to the aggregate for actual job processing
  • 6. Aggregate handles commands doing job processing and/or modifying its internal state and sending any relevant domain events.
Aggregate handles commands for actual job processing

Discussion

Both Axon and Zeebe provide excellent integration with Spring Boot via starters. This allows for quick and easy prototyping of the kind used in the proof-of-concept implementation discussed here.

Zeebe (or any other lightweight BPMN engine) can provide a valuable insight into long running business processes implemented within an event-driven application. This is especially true if a complicated compensation logic is required, i.e. cascading cancellation or timeouts. Axon’s default mechanism, Saga, can quickly become rather difficult to understand. Also, Zeebe’s modeler and workflow monitor are very helpful tools when it comes designing and monitoring workflows.

One should reflect carefully on the way Zeebe and Axon logic will be bridged together. Here we have explored one particular way where Axon’s aggregate is performing the actual job processing while Zeebe is used for modeling, visualizing and tracking workflows.

Also, please keep in mind that, at the time of this writing, Zeebe is in active state of development and will undoubtedly offer more of BPMN functionality in the future.

--

--