Bertil is a software consultant at Trivadis AG in Switzerland. Born, raised and educated in Sweden, he started an international career in software development taking him to Canada, Germany and Switzerland. He focuses on software development and architecture with Java, having a special interest on designing and building Service Oriented Architectures. He has also gained experience within MDSD and MDA as well as .Net development.
Ok, this post might be a bit longer but the topic needs some depth so bare with me
In our project, we have the following requirements regarding routing of messages:
These are just the main requirements we had, the minor I have left out. Most of the ones listed can be performed using basic functionality of Drools Expert. The JBoss ESB even comes with an action to easily integrate content based routing with Drools:
Even so, we found it difficult to fulfill the fifth requirement above, changing the routing rules without new deployment. We didn’t see how this could be easily done with the out-of-the-box actions so we decided to implement our own Content Based Router.
The solution we came up with consists of the following parts:
The database structure is simple enough consisting of the following columns:
Here is a sample content of the database table:
Using the rules defined above, when we receive a message in XML format for the context (i.e. routing group) of Account, we only need to load two routing rules from the database (the first two). The rest we can happily ignore.
Rule evaluator classes
A rule evaluator class is simply a java class which fits to the rule syntax of your choice. In the table above I have used both the common XPath (to apply on XML messages) and my own syntax (to apply on CSV messages). So you can define any rule syntax that you want as long as you implement a rule evaluator class fitting the syntax. In the example above I have defined a rule which needs a String evaluator. The rule simply defines that the evaluator should check if the String ‘Account’ is present in the content of the CSV message.
The last component of the solution is the action class performing the actual routing. Before the message can be routed, a previous action must set the message format and the routing group to the message properties so that the routing class knows which routing rules it should load from the database. After loading the routing rules from the database, the routing class applies them according to their descending priority; higher prioritized rules should be applied before rules with lower priority. After a rule was successful, the action class routes the message to the target service(s) defined for the routing rule.
How it all works together
When a message is placed in the input queue of the routing service, the routing action class method “process” is triggered. After confirming that the message format and routing group has been set by a previous service action, the action class is loading the routing rules from the database. These can be cached in order to reduce your database calls if you have a high throughput in your routing service. If they are cached you have to make sure that you don’t run into trouble if you are using a cluster of ESBs. You also have to provide a way in order to manual triggering a reload of the routing rules after you made any adjustments to the rules in the database. Anyway, after the routing rules have been loaded and sorted in a descending order based on their priority, you can iterate over them and evaluate their routing rules one after the other. When a routing rules is successful (i.e. the rule evaluator returns “true”), you route the message to the defined target service(s) using the ServiceInvoker. If there are no more routing rules with the same priority, you stop routing and ignore the rest of the routing rules.
So there you are, an alternative way of doing content based routing in JBoss ESB and keeping full flexibility of your routing rules. We are not only routing to ESB services in our project, we are also routing to jBPM processes but I left that out of this blog post in order to reduce complexity and focusing on the actual routing implementation.
Have fun with it!