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.

28 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. Definitely consider that that you stated. Your favorite justification seemed to be at the net the easiest factor to keep in mind of. 토토사이트

    ReplyDelete
  12. 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
  13. Your essay is very good. Here is yet another outstanding article.Python Fullstack Course

    ReplyDelete
  14. Java is a high-level, object-oriented, and versatile programming language that Sun Microsystems developed in the mid-1990s. It is designed to be platform-independent, meaning that Java programs can run on any device or operating system that has a Java Virtual Machine (JVM) installed. To learn more about Java check out infycletechnologies, Chennai.
    https://infycletechnologies.com/
    .

    ReplyDelete
  15. A very well article written . Keep up the good work!

    ReplyDelete
  16. THANKS FOR GIVING EVERYONE A REMARKABLY MEMORABLE POST THAT YOU’VE SHARED TO US.

    ReplyDelete
  17. Very good article, I enjoyed reading your post.

    ReplyDelete
  18. Great Information Thank you..

    ELearn Infotech Python Full Stack Developer Institute offers Full Stack with Python Django Training in Hyderabad. Our Python Full Stack Course includes from Basic to Advanced Level Python Full stack development training. We have designed our advanced Full Stack with Python DJango Training Course content based on students Requirement to Achieve Goal. We offer both Python Full stack development course classroom training and Python Full stack online training with real time projects. We are one of the leading Python Full stack training Institutes in Hyderabad. Our Course Includes Core Python, Advanced Python, Django framework, MySQL, Rest API, React JS, GITHUB, HTML, CSS, Bootstrap, Javascript, JQuery with Real time projects.

    ReplyDelete
  19. Nice statistics… thanks for share it..This post is really nice and informative. The explanation given is really comprehensive and informative.python full stack training in kphb

    ReplyDelete

Popular Posts