The following article describes a simple, JMS based, dynamic messaging
routing solution using the Sun Java CAPS suite. Although the example if
simple it is also scalable and works in all the environments I have
used. The primary reason for this blog is so that I can describe in a
future blog how to implement this using the new Java CAPS 6 environment
and what the key differences are. This said the solution described in
this article will build and run within the Java CAPS 6 Classic
environment.
Resources
Message Based Routing
The message based routing Java Collaboration (JCD) stores all its routing information within the "msgRouter.properties" file that must exist within the classpath for the server and the simplest solution to this is to place the file in the domains lib/classes directory. On first startup the JCD will read the contents of the properties file into a local Properties variable, "msgRouterProperties", which it will query later in the code to identify the required destination. This particular example will route the messages based on a JMS User property and hence does not need to know anything about the message structure or content. I would recommend that this structure always be used and if you require message based routing then add another JCD that unmarshals the message and sets the appropriate JMS property then passes then messages onto the Routing JCDs inbound queue.
You can see from the code below that the JCD initially obtains the default Message Server and Queue name to be used in the event that the routing property value can not be found in the properties file. If the default properties are not found within the properties file then the JCD will default to the Message Server and Queue Name defined in the Connectivity Map and Deployment profile.
The JCD will then attempt to obtain the Message Routing Property (TPPROPERTY) and subsequently the specific Message Server and Queue name matching that property:
JCD Code
Properties File
Resources
Message Based Routing
The message based routing Java Collaboration (JCD) stores all its routing information within the "msgRouter.properties" file that must exist within the classpath for the server and the simplest solution to this is to place the file in the domains lib/classes directory. On first startup the JCD will read the contents of the properties file into a local Properties variable, "msgRouterProperties", which it will query later in the code to identify the required destination. This particular example will route the messages based on a JMS User property and hence does not need to know anything about the message structure or content. I would recommend that this structure always be used and if you require message based routing then add another JCD that unmarshals the message and sets the appropriate JMS property then passes then messages onto the Routing JCDs inbound queue.
You can see from the code below that the JCD initially obtains the default Message Server and Queue name to be used in the event that the routing property value can not be found in the properties file. If the default properties are not found within the properties file then the JCD will default to the Message Server and Queue Name defined in the Connectivity Map and Deployment profile.
The JCD will then attempt to obtain the Message Routing Property (TPPROPERTY) and subsequently the specific Message Server and Queue name matching that property:
- Message Server : <Routing Value>.msgServerURL
- Queue Name : <Routing Value>.queueName
JCD Code
| public class
jcdMsgRouter { public com.stc.codegen.logger.Logger logger; public com.stc.codegen.alerter.Alerter alerter; public com.stc.codegen.util.CollaborationContext collabContext; public com.stc.codegen.util.TypeConverter typeConverter; private static final java.util.Properties msgRouterProperties = new java.util.Properties(); private static final String TPPROPERTY = "TRADING-PARTNER"; public void receive( com.stc.connectors.jms.Message input, com.stc.connectors.jms.JMS jmsOut ) throws Throwable { String msgServerURL = null; String queueName = null; String tpName = null; String defaultMsgServerURL = null; String defaultQueueName = null; try { // Load Properties if required if (msgRouterProperties.isEmpty()) { java.io.InputStream propIS = this.getClass().getClassLoader().getResourceAsStream( "msgRouter.properties" ); if (propIS != null) { msgRouterProperties.load( propIS ); logger.info( "*** APH-I1 : Loading msgRouter.properties" ); } else { logger.info( "*** APH-I2 : Can not find msgRouter.properties" ); } } // Trading Partner Message Property for (int i1 = 0; i1 < input.countUserProperty(); i1 += 1) { if (TPPROPERTY.equals( input.getUserProperty( i1 ).getName() )) { tpName = (String) input.getUserProperty( i1 ).getValue(); break; } } if (tpName != null && !msgRouterProperties.isEmpty()) { if (defaultMsgServerURL == null) { defaultMsgServerURL = msgRouterProperties.getProperty( "default.msgServerURL" ); defaultQueueName = msgRouterProperties.getProperty( "default.queueName" ); } msgServerURL = msgRouterProperties.getProperty( tpName + ".msgServerURL", defaultMsgServerURL ); queueName = msgRouterProperties.getProperty( tpName + ".queueName", defaultQueueName ); // Log logger.info( "*** APH-I1 : msgServerURL = " + msgServerURL ); logger.info( "*** APH-I1 : queueName = " + queueName ); // Set JMS Params if (msgServerURL != null) { if (defaultMsgServerURL == null) { defaultMsgServerURL = jmsOut.getMessageServerURL(); } jmsOut.setMessageServerURL( msgServerURL ); } if (queueName != null) { jmsOut.sendTo( input, queueName ); } else { jmsOut.send( input ); } } else { throw new Exception( "TP Name" + tpName + " does not exist or no valid properties" ); } } catch ( Exception e ) { logger.warn( "*** APH-I3 : Failed to send message", e ); if (msgServerURL != null && defaultMsgServerURL != null) { jmsOut.setMessageServerURL( defaultMsgServerURL ); } jmsOut.sendTo( input, "TP_SEND_ERROR" ); } finally { if (msgServerURL != null && defaultMsgServerURL != null && !msgServerURL.equals( defaultMsgServerURL )) { jmsOut.setMessageServerURL( defaultMsgServerURL ); } } } } |
Properties File
| default.msgServerURL=stcms://localhost:18007 default.queueName=qRouterOut partner1.msgServerURL=stcms://localhost:19007 partner1.queueName=qPartner1 partner2.msgServerURL=stcms://localhost:18007 partner2.queueName=qPartner2 |








It's nice to see that this is the same way as I am implementing a routing function :)
One question: why using 'jmsOut.sendTextTo' and 'jmsOut.sendText'? I use the plain 'send' and 'sentTo'. Doesn't the sendText put any constrains on the messsage (like being a text message)?
- Remold
Posted by Remold Krol on June 02, 2008 at 09:00 PM GMT #
Remold the reason I have sendTextTo is because the code was actually taken from an implementation where I new I would only have text messages. You are quite correct replacing it by a simple sendTo will make it more generic.
Posted by 192.18.1.36 on June 03, 2008 at 09:02 AM GMT #
hi *,
i would only recommend this functionality for CAPS 5.1.x users. afaik all other versions newer or older do not support this anymore or never have.
regards chris
Posted by Christian Brennsteiner on June 03, 2008 at 11:26 AM GMT #
Chris the setMessageServerURL was not available in ICAN 5.0.x but the sendTo was. I did specify CAPS 5.1.x because the 5.0.x release was known as ICAN.
Posted by 192.18.1.36 on June 03, 2008 at 11:58 AM GMT #
what about 6.0? i think it has been declared as "deprecated" in 6.0
regards chris
Posted by Christian Brennsteiner on June 03, 2008 at 03:34 PM GMT #
This will work in the Java CAPS 6 environment but the main purpose of the Blog was so I could write one later that compares and contrasts how to implement similar functionality using the new features available in Java CAPS 6
Posted by 82.20.139.218 on June 04, 2008 at 08:56 AM GMT #
What are the benefits of using the tip? Improve performance? Simply coding? Please advise. Thanks!
Posted by Cindy Vogel on August 29, 2008 at 03:57 PM GMT #
This simple method does provide improved performance because we can dynamically route messages around multiple message servers. In addition the routing functionality is kept within a single location (jcd)and hence the other components need only worry about implementing business functionality and then once complete pass the message on to the next stage. The example functionality implement with the entry has been used in association with the eXchange product to split the message delivery functionality onto separate domains. Because of the nature of the configuration it will allow additional trading partners to be added and they can either use an existing, low volume, delivery service or have their own created. This provide complete flexibility without having to recompile and redeploy.
Posted by 82.20.139.218 on September 01, 2008 at 01:28 PM GMT #