Content Based Routing
By: Kurt Stam (kurt.stam@jboss.com)
JBoss ESB JBoss Labs Home Page: http://labs.jboss.com/portal/jbossesb
JBoss ESB Developer Community Forums: http://www.jboss.com/index.html?module=bb&op=viewforum&f=220
########################################################################
# JBoss, Home of Professional Open Source
# Copyright 2006, JBoss Inc., and individual contributors as indicated
# by the @authors tag. See the copyright.txt in the distribution for a
# full listing of individual contributors.
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this software; if not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
########################################################################
The Content Based Router (CBR) in the JBossESB can be used to route message to the next destination based on the content of the message. By default the ESB will use JBossRules as it's evaluation engine, however this is left configurable. In the jbossesb-properties.xml there is property called 'org.jboss.soa.esb.routing.cbrClass' in the 'messagerouting' section:
<properties name="messagerouting">
<property name="org.jboss.soa.esb.routing.cbrClass"
value="org.jboss.internal.soa.esb.services.routing.cbr.JBossRulesRouter"/>
</properties>
which can be used to plug in another evaluation engine.
By default the Content Based router uses JBossRules. Read on to find how to bring up CBR, how to give it a specific rule set, and how to send a message to the CBR.
To bring up a Content-based router you need to bring up the CBR-service. Currently this is done by bringing up the CbrJmsQueueListener. To do this you need to add an xml-chapter to your deployment-config.xml that looks like the following example:
<ContentBasedRouter
service-category="MessageRouting"
service-name="ContentBasedRoutingService"
service-description="This CBR routs messages to different service destination based whether the messageType is XML or Serializable"
listenerClass="org.jboss.soa.esb.listeners.message.CbrJmsQueueListener"
connection-factory="ConnectionFactory"
destination-type="queue"
destination-name="queue/A"
jndi-type="jboss"
jndi-URL="localhost"
message-selector="service='ContentBasedRouting-SerializableOrXml'">
<cbr ruleSet="JBossESBRules.drl" />
</ContentBasedRouter>
The parameters are identical to the JMS Listener:
service-category: The category of this service, which will be used at registration time.
service-name: The name of this service, which will be at registration time. Note that both the service-category and service-name are needed to get a handle to this service.
service-description: An optional element to describe what this service does. This description is supposed to be human readable.
listenerClass: The class name of the actual listener.
connection-factory: The name of the JMS connection factory.
destination-type: This can be either queue or topic.
destination-name: The name of the queue (or topic).
jndi-type: The type of naming service. For now this is limited to “jboss”, but we should soon support most other naming services.
jndi-url: The uri used to communicate to the naming service.
message-selector: The JMS message selector on the queue defined above. This needs to be of the format “service='<some string>'”
Then it is followed by a child element call “cbr”, which is specific to the rule based content based router. It can contain to elements:
ruleSet: The set of rules that should be used to evaluate the content. Only 1 ruleSet can be given for each CBR. Just define more router if you need composite CBR routing.
ruleLanguage: In JBossRules you can define a custom (business) language. This (optional) field can be used to pass in that custom language to go with the defined ruleSet.
A rule set can be created using the JBossIDE which includes a plug-in for JbossRules. Figure 1 shows a screen shot the plug-in.
Figure 1. JBoss Rules IDE. Create a new ruleSet.
To add a new rule simple click on “New Rule resource”. Make sure your rules import at least
import org.jboss.soa.esb.message.Message;
The message will be asserted into the working memory of the rules engine. You can use sub objects of message in your evaluation. This is demonstrated in the JBossESBRules.drl ruleSet where the rule checks if the type is XML or Serializable. Secondly you have to make sure to define:
global java.util.List destinationServices;
The destinationServices List is returned and should contain one or more destination services. The format of the destination service should be:
<service-category>:<service-name>
If you save your rule into the product/core/services/rules package it will be jarred up into the jbossesb-rules.jar. However as long as you your rules on the classpath somewhere JBossRules should find it.
For XML-based messages it is convenient to do XPath based evaluation. For this we ship a custom rule language defined in the XpathLanuage.dsl. To use it you need to reference it in your ruleSet with:
expander XPathLanguage.dsl
and you need to pass it in the name of this file in the cbr child element like:
<cbr ruleSet="JBossESBRules-XPath.drl" ruleLanguage=”XPathLanguage.drl”/>
Currently the XPath Language makes sure the message is of the type JBOSS_XML and it defines
xpathMatch “<element>”: yields true if is an element by this name is matched.
xpathEquals “<element>”, “<value>”): yields true if the element is found and it's value equals the value.
You can define your own Custom Rule Language.
Now that we have a CBR up and running and listening we can send it messages. To to this you need to add it in as an action somewhere in your action-pipeline. For example you can add this following fragment:
<action name="TestDefaultRouteAction"
class="org.jboss.soa.esb.actions.CbrProxyAction"
service-category="MessageRouting"
service-name="ContentBasedRoutingService"
process="route" />
Where
class: the name of the action class.
service-category: the service category of the service that needs to be called (the CBR)
service-name: the name of the category of the service that needs to be called (the CBR)
process: the name of the method on the CBR-action, this can be any of
routeAndDeliver: route and deliver the message to the destination(s).
route: route the message and return a message with a list of destinations attached to it.
deliver: just deliver. A message that was routed before will be delivered to its destination(s)
The separation of route and deliver allows for other actions (like message transformation) to be inserted between routing and delivering.