Ok, this post might be a bit longer but the topic needs some depth so bare with me Smiley

The requirements

In our project, we have the following requirements regarding routing of messages:

  1. The incoming messages must be routed based on their content
  2. The message content can be on different formats, for now XML and CSV but maybe more in the future
  3. One message can be routed to more than one target service
  4. The routing rules must be applied according to their priority and routing should stop when a routing rule was successful
  5. The adjustment of the routing rules must be possible during runtime without deploying new deployment units to the JBoss ESB

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:

org.jboss.soa.esb.actions.ContentBasedRouter

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

The solution we came up with consists of the following parts:

  • Database table containing routing rules
  • Rule evaluator classes to evaluate the defined rules on a specific message
  • Action class to perform routing based on the definitions in the database

Database structure

The database structure is simple enough consisting of the following columns:

  • Format – The format of the incoming message to avoid applying unnecessary routing rules. Makes no sense to apply a routing rule for XML on a CSV message.
  • Routing Group – Defines the group to which the routing rule belongs. We are performing routing on more than one place in our ESB but we store all routing rules in the same database table. By introducing routing groups we can easily pick out the routing rules applying for each context.
  • Priority – The priority of the routing rule, higher priority meaning the rule is applied earlier.
  • Routing Rule – A routing rule defined in any syntax of your choice. It can be an XPath expression but also an entirely Domain Specific Language, whatever fits best for your routing context.
  • Rule Evaluator Class – The fully qualified class name to the java class which can evaluate the routing rule defined in the previous column.
  • Target Services – The service(s) to which the message should be routed if the routing rule is successful. For each target service, the category and name is needed. One can also define a comma separated list of target services.

Here is a sample content of the database table:

image

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.

Action class

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! Smiley