During my years on the Mule Community forum I’ve noticed that there are some problem areas that are more common than others. One recurring question, that I thought I should address here, is how to preserve message order in JMS.
The first solution coming to mind is to use exclusive consumer, but I’ve come to realise that there are some disadvantages with exclusive consumer such as having active consumers doing nothing (I don’t like the idea of having workers ready to dig in but they are not allowed to). Another thing is that, with exclusive consumer, a message might block another message even though they really don’t have anything to do with each other. For example, let’s say we’re dealing with car orders, then you probably don’t want a order for a Volvo, that doesn’t go through, to block a order for a Saab (I’m Swedish).
An alternative would be to use JMS message groups. With message groups you can guarantee ordering of related messages, you get load balancing across multiple consumers and auto failover to other consumers if JVM goes down. What that means is that all messages in a group will be delivered to the same consumer as long as it’s available but will switch to another one if that one goes away. Different groups will also be dispatched on different consumers depending on load, illustrated by image below:
So, how to implement message groups? It’s very simple, the only thing you have to do is to set the JMSXGroupID property on the client producer (outbound endpoint) before sending it off. By default, all messages will be delivered in the same order as they arrived but it’s also possible to set the JMSXGroupSec property to control in which order different messages should be delivered.
To illustrate this with Mule and ActiveMQ I will show you a config that read orders from a xml file. Two orders for Volvo and one for Saab, like:
I will use type as message group id. I will also use a retry policy and provoke an exception for the first Volvo order just to show that the Volvo V70 will be send X times before the Volvo C30 gets consumed. Meanwhile the Saab order will slide through since it’s not part of the same group.
If you take a look at the log after processing the file it will show that the Volvo V70 order will be consumed 3 times before it’s committed, and not until then the Volvo C30 order will be consumed (sequence is remained). Meanwhile the Saab 9-5 order has been consumed as expected since it’s not part of the same group.
Log output (stripped from the provoked exception trace):
Note: JMSXGroupID is part of the JMS spec but I’ve only evaluated this using ActiveMQ. From what I can see in documentation it should be supported by the most common platforms. Please feel free to comment if you have experience from using message groups with other platforms.
This is a guest post from Mule community member Tomas Blohm. Thank you Tom! (we’ll be sending you a cool T-shirt). If anyone else in the Mule community would like to write a guest post, please email us.