Monday, February 20, 2006

JMS backed by Websphere MQ

This is a learning experience about a JMS queue backed by Websphere MQ. My initial understanding was that a message published on the MQ queue wouldn't invoke the onMessage method of a listener/MDB. The notion sounded logical as the Java/JMS equivalent of the message exposed by the MQ JMS is of type com.ibm.mq.JMSBytesMessage and the onMessage expects the argument to be of type javax.jms.Message. Yesterday, we were able to publish a message on MQ and get an MDB listen to the messages. The details follow...

Before getting into the nitty-gritty, some backdrop on the context - our requirement was to process messages put on the MQ "asynchronously". Our knowledge of MQ being naive, the task motivated us and we explored the MQI(java interface for MQ) and played with it by developing some sample code. This led to the roll out of a design using the MQI and the quartz scheduler. I named it the "Pull Approach". A quartz job would poll the MQ at a defined time intervals and retrieve any messages in the MQ queue. Developed the code for the Pull approach and gave a demo of it.

Intrigued by the challenge and exploring more, came up with a second design that would use the inbuilt features of the MQ. A trigger is invoked on publishing a message. The trigger "translates" the message to JMS compatible message and publishes the message on a Topic. This design was baptized as "Push Approach" as the MQ server was pushing the messages. A document has been prepared with both the approaches and with crisp state diagrams made using Rational Rose and circulated it across. There was an inherent flaw in the Push approach, it didn't give implicit support for transactions. There were mixed opinions amongst the folklore about the the approaches with offhsore favoring Pull and onsite for Push.

With adrenalin still gushing, we got more adventurous and explored the JMSAdmin of the MQ. We have been playing around with that for a while but couldnot hit the bush.We decided to give try it afresh from scratch. So, created a context in the JMSAdmin, bound the connection factory and queue to the JNDI, used the same bindings in the JMS configuration on Websphere App server. The prototype was ready for testing. And to our surprise, when we pubslished a message on the MQ, it did invoke the MDB, though there was a ClassCastException for com.ibm.jms.JMSBytesMEssage. The cast exception could be resolved by reading out the bytes out of the JMSBytesMessage and copying them onto the JMS TextMessage.

This was an interesting development, indeed. Although, the earlier two approaches would be promptly decommissioned in favor of the third approach, we are happy that we were able to suggest a robust design that leverages the inbuilt features of the product. The learning curve has taken off. The documentation and the articles found on the IBM developer works site didn't help us much and most of the examples appeared to ratify our initial understanding. Well, being li'l adventurous and thinking outta box does help sometimes. There will a sequel to this blog entry soon with gory technical details.

*** UPDATE ***
There is an article on IBM site that explains in detail about configuring Weblogic JMS for Websphere MQ. Read the article here. I wish the article would have been published earlier that would have saved a few days of my tussle .

Thursday, February 09, 2006

Tussle with Websphere

Has been working with a variety of App. servers like Weblogic, JBoss, and JRun, but never got a chance to work with Websphere. Recently, got a chance to work with Websphere suit of products. First the websphere MQ and then the websphere server itself. The experience with MQ was bit adventurous, as the technology predates JMS. With some trial and error, intuition, googling, got the things up and running. Reb books helped a lot in understanding the internals for MQ.

To test the use cases against our design, we decided to develop a vertical slice of the application. One part of the slice was an MDB that listens to a JMS Queue on the websphere, backed by the MQ. The task is broken to two parts - have an MDB listening to the JMS queue on webspshere and once part 1 is in place, configure a MQ as a backend for the JMS queue. Developing an MDB was no much hassle and it got deployed on the websphere(The server had to be bounced everytime after configuring the Listener Ports and registering the Queue with the JMS server, and after deploying the jar file with MDB, duh, it sucks!). The next step was to publish some messages on the queue and see if the onMessage of the MDB is getting called.

I developed a suit of small utilities to help me in server-side testing, which I call as the fixture. The configuration of the fixture is externalized to facilitate portability. The messaging fixture worked without any errors when it was pointing to Weblogic, JBoss, JRun. But with Websphere, a lot of tweaking of the classpath is required. The following is the summary of the tweaking:

1. First of all, use the JDK that comes with the server, located at ${was_home}/java. If you don't, you'll waste a couple of hours like me.

2. Place these jars in the classpath:
com.ibm.mq.jar
com.ibm.mqjms.jar
dhbcore.jar
ecutils.jar
j2cImpl.jar
j2ee.jar
messagingClient.jar
naming.jar
namingClient.jar
namingserver.jar
webcontainer.jar
Properties folder. Place all or you'll repent.

3. Websphere works on iiop. So the JNDI props will be com.ibm.websphere.naming.WsnInitialContextFactory and iiop://localhost:2809.

To figure out what jars go in the classpath, it took me almost 6 hours. Extensive googling and some experimentation made the things work. It seems most of the people had a similar experience. Looks like I'm going to have some more tussles with websphere in the near future. Why can't the Websphere be as developer friendly as Weblogic.