How to process messages in sequence with BusinessWorks

Emmanuel Marchiset
7 min readJan 16, 2022

It is a quiet common requirement in integration projects to have to process some events, generally in the form of messages handled by a Messaging solution, in the same order as they were sent by the source application.

The typical example is the processing of orders coming from an online store, where a customer may create an order, update it, update it again and finally delete it, all in a few seconds time frame. It is quiet easy to understand that in such cases the events related to the orders need to be processed in sequence while the back-end system will not be able to update or delete an order that would not be already created at its end.

As seen in the example above the requirement to process events in sequence is usually for events that are related to a given instance of a business object (like for example an order), which means that events related to different instances of the same business object (different orders) can be processed in any order. That said there are some cases where all events in a flow have to be processed in sequence.

Considering this requirement there are two layers to look at:

. The transport layer: to process events in sequence the transport layer must be able to guarantee that message are delivered in the same order as they were sent in the destination used to manage the flow. This is the default behavior of common Messaging solutions like TIBCO EMS, TIBCO FTL and Kafka (within a partition) so this requirement is addressed (see the note below about Kafka).

. The processing layer: the BusinessWorks engine is multi-threaded and is quiet often deployed in active / active configurations at runtime. In such context multiple events are processed at the same time in different threads and different engines so in sequence processing cannot be guaranteed. This is because even in a single engine configuration a thread started after another may complete its execution before and obviously in a multiple engines configuration an engine could be faster than the other simply because the underlying host would be less loaded.

That said it is still possible to use BusinessWorks in a way that would ensure that messages are processed in sequence.

This article presents some possible approaches in the context of the use of a JMS transport, note that the same approaches can be used with other Messaging solutions like TIBCO FTL and Kafka.

The different approaches described in this article can be used with BusinessWorks 6.X, BusinessWorks Container Edition and BusinessWorks 5.X.

Note that in all the following approaches sequencing is managed for a single Producer instance.

# A single thread on a single engine

The most obvious solution is to configure the JMS Receive Message activity to use a single thread and to run the application on a single appnode. In that approach, only one message will be processed at a time and then message will be processed in sequence.

For the JMS Receive Message activity to use a single thread just use Client Acknowledgement with Client Session set to 1 :

JMS Receive Message activity configured to process messages one by one

To run the application on a single appnode you can deploy it in an appspace configured with a single appnode or an appspace configured with two appnodes running in active / passive mode. See the following article for explanations on how to set-up such configuration:

https://emarchiset.medium.com/how-to-set-up-an-active-passive-configuration-in-businessworks-6-x-f805fe4619a3

This approach is easy to set-up but its limit is that messages are processed one by one and then processing is not very fast. This can be a problem if the flow have to be processed in a limited time frame or this there is a high throughput of messages.

Still note that this approach is the only available if all events in a flow have to be processed in sequence.

# Multiple threads on a single engine

As mentioned in the introduction, this is quiet common to have to manage the requirement to process events in sequence only for events that are related to a given instance of a business object.

The good news here is that in BusinessWorks there is a mechanism allowing to process multiple events at the same time on a given engine while ensuring that events related to the same ‘key’ (for example an order id) are processed in sequence.

To use this mechanism with JMS messages you need to be able to extract from the received JMS message the identifier of the related business object (for example the order id). This is possible if the JMS message body is in XML format and the identifier is part of the XML document or if the identifier is managed as a JMS message property.

You also need to run the application on a single appnode as in the previous case.

In this approach the JMS Receive Message activity can be configured with the usual best practice (use Client Acknowledgement with Max Session defined by a property) and a message type of ‘XML Text’ :

JMS Receive Message activity configured to process multiple XML messages in parallel

Then the XML schema used to define JMS Receive Message activity output has to be set, for example:

Configuration of a JMS Receive Message activity output schema

Then the Sequence Key has to be defined in the ‘Advanced’ tab:

Configuration of a JMS Receive Message activity to use a Sequence Key

If the message is not in XML format you can use JMS message properties, that then have to be set by the Producer application, for explanations on how to access JMS message custom properties from BusinessWorks you can refer to the following article:

https://emarchiset.medium.com/how-to-use-jms-application-properties-in-businessworks-6-x-and-businessworks-container-edition-2b080045bcbf

At the end this approach is also easy to set-up, multiple messages can be processed at the same time while managing the requirement to process messages related to the same ‘key’ in sequence but we are still limited to a single engine.

This approach is commonly used on projects.

# Multiple threads on multiple engines

This approach can also be used to manage the requirement to process events in sequence only for events that are related to a given instance of a business object.

It is using a design pattern based on the following principles:

. Use multiple queues, each of them being a channel where message are sent and delivered in sequence

. On Consumer side use a BusinessWorks application instance per queue, each instance reads messages from the queue it is attached to and uses multiple threads to process messages with a Sequence Key to ensure messages related to the same ‘key‘ are processed in order (Multiple threads on single engine approach)

. On Producer side the ‘key’ (for example the order id) is used to calculate a number used to identifies the queue to use to transport the message (all messages with number ‘1’ will go to Q1, all messages with number ‘2’ to Q2 and etc). Doing this all messages related to the same ‘key’ always goes to the same queue and are then transported and processed in order.

The number to identify the target queue can be calculated using a ‘modulo’ from the ‘key’ (for fields of type number you can use the XPATH function ‘mod’, for string you can use the function sum(string-to-codepoints(“<string>”)) to first get a unique number from the string).

Illustration of the pattern that can be used to manage sequencing on multiple application instances

This approach is a bit more complicated to set-up and Producer applications have to take into account the use of multiple queues but we can now process messages related to the same ‘key’ in sequence in a multiple threads and multiple engines configuration.

Reference elements

For reference elements on this topic, and an additional approach using a ‘sequencer’ component, I would recommend to check the book ‘Architecting Composite Applications and Services with TIBCO’ written by my esteemed and now former colleague Paul C. Brown, this topic is covered in the ‘Load Distribution and Sequencing Patterns’ chapter.

This book is available on Amazon.

Note about Kafka

In the highly-scalable architecture of Kafka, where message flows are distributed over multiple partitions handled by different brokers, in sequence processing can only be guaranteed in the context of a single partition.

To process messages in sequence you then have to use a single partition or the approach suggested above in the multiple engines approach to make sure all messages related to a given instance of a business object are always written to the same partition.

For details about Kafka you can refer to following section of the Kafka documentation :
https://kafka.apache.org/28/documentation.html#intro_concepts_and_terms

--

--

Emmanuel Marchiset

I work as an Architect at TIBCO Software on Integration products. Opinions here are my own.