Tuesday, March 15, 2011

Messaging With WebSphere MQ Using Spring JMS

Spring JMS provides a simple API to work with JMS implementations. This post describes how to use Spring JMS to communicate with IBM WebSphere MQ. The code has been tested with WebSphere MQ version 7.0.1. Maven is used as the build tool. It is also used to resolve the WebSphere MQ and other dependencies. Only relevant code snippets are listed below - for the complete source, please refer to the link at the bottom of this post.

To start off we need to obtain the WebSphere MQ JARs. These JARs are proprietary - hence they will not resolve through a public Maven repository like Maven Central. These JARs need to be obtained from the WebSphere MQ installation directory and manually deployed to our local Maven repository. The config below defines the WebSphere MQ dependencies in our Maven POM file.

Spring's JMSTemplate class is the key to simplifying access to the conventional JMS API. It abstracts the common and repetitive boiler-plate code by handling the creation and closing of connections and sessions, sending and receiving of messages and handling of exceptions. JMSTemplate and a few other beans need to be defined in our Spring config.

MQQueueConnectionFactory defines the connection to the Queue Manager. Next we define SingleConnectionFactory102, DynamicDestinationResolver and finally JmsTemplate102. The 102 suffix implies that our underlying JMS implementation version is 1.0.2. Now that our configuration is complete, we can send and receive JMS messages.

To send a JMS message, we use the send(String destinationName, MessageCreator creator) method of JMSTemplate.

To receive a message, we use the receive(String destinationName) method.

As we can see, Spring's JMSTemplate really simplifies and speeds-up connecting to a JMS provider like WebSphere MQ.

Sample Source Code
A fully functional example Maven application accompanies this post. It provides the complete source code mentioned in this post. It can be downloaded at GitHub using the link below.

8 comments:

Hearty said...

Hi,

Thanks for this post. I'm learning JMS + Spring and I've setup a project using the sample code provided. But when I execute a test to send and recieve the msg from a MQ, it is failing. There is no error/exception shown while sending the msg but it does not send it to the MQ. Reading the msg shows the msg as null.

Please provide any inputs to resolve this.

Thanks,
RJ

Sputmayer said...

Hi Albert,
I downloaded your sample but when I try to compile the same I got some errors regarding class dependencies. I added that missing jars to pom.xml and finally got to the point where tests start to run However I get an error when trying to create the mqConnectionFactory bean. I have put the main error data below.


Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mqConnectionFactory' defined in class path resource [spring.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibm.mq.jms.MQQueueConnectionFactory]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:955)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:901)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:574)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
... 30 more
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibm.mq.jms.MQQueueConnectionFactory]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:71)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:948)
... 44 more
Caused by: java.lang.NullPointerException
at com.ibm.msg.client.jms.internal.JmsFactoryFactoryImpl.getInstance(JmsFactoryFactoryImpl.java:169)
at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.setProviderFactory(JmsConnectionFactoryImpl.java:176)
at com.ibm.mq.jms.MQConnectionFactory.(MQConnectionFactory.java:286)
at com.ibm.mq.jms.MQQueueConnectionFactory.(MQQueueConnectionFactory.java:76)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at

I can email you my pom.xml and sping.xml. However I have used hermes to connect using com.ibm.mq.jms.MQQueueConnectionFactory and the same properties that I specify via spring which works fine for me. Can you please help me on this one.
Thanks
Sandeep Rai

Haris said...



i m getting jmsTemplate null error , please advice me,
haris.send@gmail.com

************* wmq test **************
Apr 18, 2013 10:24:34 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b05acd: startup date [Thu Apr 18 22:24:34 CST 2013]; root of context hierarchy
Apr 18, 2013 10:24:35 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Apr 18, 2013 10:24:35 PM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [main.properties]
Apr 18, 2013 10:24:35 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@838de0: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,mqConnectionFactory,jmsQueueConnectionFactory,jmsDestinationResolver,jmsQueueTemplate,messageService]; root of factory hierarchy
jmsTemplate > null
Exception in thread "main" java.lang.NullPointerException
at com.test.testspringjmsmq.MessageService.readMessage(MessageService.java:46)
at com.test.testspringjmsmq.MessageServiceTestMain.main(MessageServiceTestMain.java:23)

Unknown said...

I fixed this error when I changed my JDK from IBM to ORACLE/SUN. may be IBM JDK, the one inside Websphere, doesnt have all the required things.

Raja said...

I tried this approach and I am getting below error.

JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED')".
How can we set the user id and password to make the authentication successful.

Sumit said...

http://awhite.blogspot.com/2013/06/jms-spring-mq.html this can help to set the user name and passowrd.

Unknown said...

Make the service to run with username MUSR_MQADMIN. Try to reset the password of MUSR_MQADMIN in user accounts(control panel). Specify this user name and new password as authentication parameters to prevent 2035 authorization error.

NaveenJAVA said...

can we connect IBM mq using spring jms without ibm dependencies