Tuesday, December 12, 2006

Implementing JMS with Spring: Messaging Client

Last week, I described how to implement JMS, using a stand-alone client and a Message Driven Bean. In this post and the next, I will describe how to implement JMS using Spring and Message Driven POJOs. This post will describe how to create a Messaging client using Spring. The next post will describe how to implement a Message driven POJO. For this I used a simple servlet that, when invoked will send a text message "hello", to a destination queue. The Message driven pojo, listening on the queue will then receive and print the message. Follow these steps to run the example
  1. Setup the JMS environment as described in the "Configuring Weblogic JMS" post
  2. Create the Messaging client: This is a simple Java class which uses the spring JmsTemplate to send a message to the queue. The JmsTemplate can be used for message production and synchronous message reception. For asynchronous reception, Spring provides a number of message listener containers that are used to create Message-Driven POJOs (MDPs).
    public class QueueSender {
    private JmsTemplate jmsTemplate;
    public void setJmsTemplate(JmsTemplate jmsTemplate) {
    this.jmsTemplate = jmsTemplate;
    }
    public void sendMesage() {
    jmsTemplate.send("jms/testQueue", new MessageCreator() {
    public Message createMessage(Session session) throws JMSException {
    return session.createTextMessage("Hello");
    }
    });
    }
    }
    QueueSender.java
  3. Configure the Bean in the applicationContext.xml file: The following is alisting of the applicationContext.xml file.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
    <props>
    <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
    <prop key="java.naming.provider.url">t3://localhost:20001</prop>
    </props>
    </property>
    </bean>

    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="jndiName">
    <value>jms/connectionFactory</value>
    </property>
    </bean>

    <bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="cache">
    <value>true</value>
    </property>
    </bean>

    <bean id="queueTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
    <ref bean="queueConnectionFactory" />
    </property>
    <property name="destinationResolver">
    <ref bean="jmsDestinationResolver" />
    </property>
    </bean>

    <bean id="jmsSender" class="jms.QueueSender">
    <property name="jmsTemplate">
    <ref bean="queueTemplate" />
    </property>

    </bean>
    </beans>
    WEB-INF/applicationContext.xml

    The JndiDestinationResolver class can be used to obtain the Queue destinations using the JNDI Name. The send method in JmsTemplate (see QueueSender), uses the JNDI name, which is used by the JndiDestinationResolver to obtain the appropriate destination.

  4. Create a servlet to invoke the Message Sender: The following servlet is used to invoke the QueueSender:
     public class QueueSenderServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
    QueueSender sender = (QueueSender)ctx.getBean("jmsSender");
    sender.sendMesage();
    }
    }
    QueueSenderServlet.java
  5. Update the web.xml file to add the servlet and spring application context:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>SpringJMSClientWeb</display-name>
    <servlet>
    <description></description>
    <display-name>QueueSenderServlet</display-name>
    <servlet-name>QueueSenderServlet</servlet-name>
    <servlet-class>jms.QueueSenderServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>QueueSenderServlet</servlet-name>
    <url-pattern>/QueueSenderServlet</url-pattern>
    </servlet-mapping>
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    </web-app>
    web.xml

    The listener defined web.xml (ContextLoaderListener) by default loads the applicationContext.xml file in WEB-INF directory of the web application.
In the next post, we will see how implement the Message Driven POJO to consume the message sent from here.

29 comments:

  1. Thanks for the post it was a good example.

    I have a question about throwing RuntimeException on the onMessage method.
    If a Runtime exception occurs, shouldn't the message still be in the queue, and possibly resent until the onMessage can complete without exception?
    When I throw an exception I lose the message, which isn't a good thing!

    ReplyDelete
  2. Ok, seems that I have to explicitly set the session transacted flag to true in the DefaultMessageListenContainer.

    With that flag set the message is resent until the onMessage method completes without exception.

    Thanks again for the post.

    ReplyDelete
  3. Hi,
    I tried the example and I tried to deploy it to tomcat. But during deployment I am getting this error although I have my weblogic 10 instance running on my PC.
    I included all possible jar files to the classpath.
    SEVERE: Context initialization failed
    org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.NoClassDefFoundError: weblogic/utils/NestedException
    Caused by: java.lang.NoClassDefFoundError: weblogic/utils/NestedException

    ReplyDelete
  4. Hi,
    I tried the example and I tried to deploy it to tomcat. But during deployment I am getting this error although I have my weblogic 10 instance running on my PC.
    I included all possible jar files to the classpath.
    SEVERE: Context initialization failed
    org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.NoClassDefFoundError: weblogic/utils/NestedException
    Caused by: java.lang.NoClassDefFoundError: weblogic/utils/NestedException

    Thanks for the example,
    Mohan

    ReplyDelete
  5. Good job! Could you post the solution on how you would consume the message using a MDP?

    ReplyDelete
  6. Hi!
    What version of Spring was used in sample?
    I'm having a NameNotFoundException in the jndiName from bean queueConnectionFactory.

    ReplyDelete
  7. Good Job!! will you please post the solution for Synchronous messaging with temporary queue and spring jms template.

    ReplyDelete
  8. I could use this with spring2.0. jboss messaging . I tried this from a POJO.

    Infact in abhi's sample destination is resolved in run time . i had configured my destination directly in the config file, it worked .

    ReplyDelete
  9. Very good article. Liked it. it is very helpful for me

    ReplyDelete
  10. This post is really nice and informative. The explanation given is really comprehensive and informative.

    oracle training

    ReplyDelete
  11. Infycle Technology, No.1 Software Training Institute in Chennai, afford best Data Science training in Chennai and also provide technical courses like Oracle, Java, Big data, AWS, Python, DevOps, Digital Marketing, Selenium Testing, etc., and we also provide the best training from the best technical trainers and after completion of training students will be able to crack the jobs on top MNC’s. for more information call 7504633633.

    ReplyDelete
  12. Definitely consider that that you stated. Your favorite justification seemed to be at the net the easiest factor to keep in mind of. 토토사이트

    ReplyDelete
  13. Very efficiently written information. It will be valuable to everyone who utilizes it, as well as yours truly. Keep doing what you are doing – for sure i will check out more posts.
    경마
    온라인경마

    ReplyDelete
  14. Your article is very interesting. I think this article has a lot of information needed, looking forward to your new posts.
    스포츠토토

    ReplyDelete
  15. Get your Career in IT on track with our Career Accelerator Program by Premium Learnings

    Check our Youtube channel for our training videos - https://www.youtube.com/c/PremiumLearningssystem

    For more info do visit us: https://www.premiumlearnings.com/

    ReplyDelete
  16. Thanks for such a great blog here. I was searching for something like this for quite a long time and at last, I’ve found it on your blog. It was definitely interesting for me to read about their market situation nowadays.
    best c online course
    online oracle
    c course
    cheap website design in chennai
    big data training online

    ReplyDelete

Popular Posts