JMS API is Java Message Service API that allows components to communicate asynchronously. JMS enables two components to send and receive message without knowing each other. Spring provides support for JMS programming. Spring is a widely used framework to develop enterprise applications. It is bundled with many APIs like AOP, IOC, Spring MVC, Spring JMS, etc. This article can be used by beginners to write simple programs using Spring API to integrate with Weblogic JMS . Here weblogic is used because it supports many features to provide communication between sender and receiver. It acts as a middleware for JMS applications.
1)Why do we need JMS?
Enterprise Applications is software to solve enterprise problems. It has many business requirements to solve the problem. To have better modularity, the requirements will be developed as different software components and the programmer will integrate these components to complete the entire enterprise application. The programmer needs to consider many factors while integrating the components. The following scenarios will give a clear picture about some factors with respect to component integration
also read:
Scenario #1:
Assume that there are two components called OrderProcessing and CreditCardVerification. The OrderProcessing component needs to communicate to the CreditCardVerifcation but it is not having the interface of the CreditCardVerification.
How it is going to communicate?
Scenario #2:
Assume that there are two components called TransactionBean and HistoryBean(to record each transaction). For each transaction, the TransactionBean is going to send information to the HistoryBean and it doesn’t want to wait till the HistoryBean completes the work.
How to develop the TransactionBean to have asynchronous communication to HistoryBean?
The solution is provided by JMS.
2)Introduction to JMS API
JMS API is Java Message Service API that allows components to communicate asynchronously. JMS enables two components to send and receive messages without knowing each other. Messaging provides communication between software components or applications. A messaging component can send messages to, and receive messages from, any other component. This is achieved with the help of JMS Provider. The JMSProvider is a MOM (Message Oriented Middleware); sitting between sender and receiver components for asynchronous communication i.e. if a sender sends a message, the same will be stored inside MOM. The MOM then forwards the message to the receiver.
To achieve the communication, the following components will be configured inside the MOM.
- Connectionfactoires: Provides the communication to client programs
- Destination: Stores the messages. There are two types.
- Queue: The message will be delivered to Only one receiver
- Topic-Message will be delivered to more than one receiver
3) Weblogic JMS Provider
One of the widely used providers is Web logic. It is widely used because of the following features.
- Provides messaging API.
- Supports clustering.
- Platform independent.
- Resources can be configured using the Web Logic Administration Console.
- Supports XML messages.
- Supports multicasting delivery.
4) Spring JMS API
Spring supports a JMS framework that simplifies the complexity of the JMS implementation. The package org.springframework.jms.core provides the API for JMS core functionality. A JMS Programmer can write JMS application using Spring IOC and Spring JMS API easily. Using Spring JMS and Dependency injection, the JMS configuration details are migrated from Java code to XML file
The Spring JMS API supports a template mechanism to hide the details of Java APIs. Programmers can use JDBC Template and JNDI Template classes to use Web logic JMS resources. Spring supports the JMS Template, so developers don’t have to write complex code for JMS implementation. Templates are helper classes used to reduce the complexity of JMS and handle the creation and release of JMS resources like connection factories, destinations, and sender/receiver objects.
We attempt to provide you, in this article, a step by step solution for Integrating Spring, JMS, and Web logic. It is addressed to the audience who are aware of the basics of Spring IOC, Web logic, and JMS. The article also provides detailed information about the JMS implementation using Spring JMS. This article will help the programmer to write a JMS application using Spring. Programmers can use the configuration file as a basic setup for JMS applications in addition they can develop applications as well.
5) Steps to integrate Spring JMS and Weblogic
Step 1:
- Configure the following JMS resource inside the web logic server.
- ConnectionFactory- jms/connectionFactory and
Queue Destination- jms/testQueue
Step 2:
Create a dynamic web application in the Web logic workshop
Step 3:
Import Spring.jar,
Commons-logging.jar and
log4j-1.2.15.jar
Step 4:
Create the InvoiceQueueSender class in the package jms. The class InvoiceQueueSender is used to send messages. The JMSTemplate is injected into InvoiceQueueSender using an IOC container. JMS Template is used for sending and receiving messages using Message Creator. The Message Creator is a call-back interface that has createMessage to create messages. JMS Template has a send method that takes the parameter, Queue name, and message creator.
Sample Code
package jms; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.Session; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.MessageCreator; public class InvoiceQueueSender { private JmsTemplate jmsTemplate; public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendMesage() { MessageCreator messageCreator=new MessageCreator() { public Message createMessage(Session session) throws JMSException { return session.createTextMessage("I am sending Invoice message");} }; jmsTemplate.send("jms/testQueue", messageCreator); } }Step 5:
Create the InvoiceMDB class in the package jms. It is a MessageDrivenBean. The InvoiceMDB is an MDB and it implements the MessageListener interface. The onMessage will be executed automatically whenever a message is delivered to the Queue or Topic.
Sample Code
package jms; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; public class InvoiceMDB implements MessageListener { public void onMessage(Message message) { try { System.out.println(((TextMessage) message).getText()); System.out.println("Hello"); } catch (JMSException ex) { throw new RuntimeException(ex); } } }Step 6:
The following details will be configured inside the spring configuration file. Here the file name is applicationContext.xml.
JNDITemplate
It helps us to perform JNDI operations. It has methods to do lookup and binding operations. The web logic context details are configured using this interface.
<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:7001</prop> </props> </property> </bean>JndiObjectFactoryBean
It is used to look up the JNDI object on startup and cache it. This interface is used to configure the connection factory.
<bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate" /> </property> <property name="jndiName"> <value>jms/connectionFactory</value> </property> </bean>DestinationResolver
It is used by JmsTemplate to resolve destination names
<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>JMSTemplate
It is used to send messages. This requires information about the connection factory and destination resolver while configuring.
<bean id="invoiceQueueTemplate" class="org.springframework.jms .core.JmsTemplate"> <property name="connectionFactory"> <ref bean="queueConnectionFactory" /> </property> <property name="destinationResolver"> <ref bean="jmsDestinationResolver" /> </property> </bean>Queue
The destination details will be configured using JndiObjectFactoryBean
<bean id="invoiceQueue" class="org.springframework .jndi.JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate" /> </property> <property name="jndiName"> <value>jms/testQueue</value> </property> </bean>MDB(MessageDrivenBean)
The details about Message driven will configured as a normal bean
<bean id="invoiceListener" class="jms.InvoiceMDB" />Listener Configuarion
This class is used to configure the normal bean as a message-driven bean. While configuring, the destination details will be supplied so that the framework can have the relationship between MDB and the destination
<bean id="Invoicelistener" class="org.springframework.jms .listener.DefaultMessageListenerContainer"> <property name="concurrentConsumers" value="5" /> <property name="connectionFactory" ref="queueConnectionFactory" /> <property name="destination" ref="invoiceQueue" /> <property name="messageListener" ref="invoiceListener" /> </bean>SenderBean
<bean id="jmsInvoiceSender" class="jms.InvoiceQueueSender"> <property name="jmsTemplate"> <ref bean="invoiceQueueTemplate" />The final contents will be
<?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="invoiceListener" class="jms.InvoiceMDB" /> <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:7001</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="invoiceQueueTemplate" class="org.springframework .jms.core.JmsTemplate"> <property name="connectionFactory"> <ref bean="queueConnectionFactory" /> </property> <property name="destinationResolver"> <ref bean="jmsDestinationResolver" /> </property> </bean> <bean id="jmsInvoiceSender" class="jms.InvoiceQueueSender"> <property name="jmsTemplate"> <ref bean="invoiceQueueTemplate" /> </property> </bean> <bean id="invoiceQueue" class="org.springframework.jndi .JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate" /> </property> <property name="jndiName"> <value>jms/testQueue</value> </property> </bean> <bean id="Invoicelistener" class="org.springframework.jms .listener.DefaultMessageListenerContainer"> <property name="concurrentConsumers" value="5" /> <property name="connectionFactory" ref="queueConnectionFactory" /> <property name="destination" ref="invoiceQueue" /> <property name="messageListener" ref="invoiceListener" /> </bean> </beans>Step 7:
Create Servlet to send message
package jms; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; public class InvoiceSenderServlet 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()); InvoiceQueueSender sender = (InvoiceQueueSender) ctx .getBean("jmsInvoiceSender"); sender.sendMesage(); } }Step 8:
Configure the spring configuration details in the web.xml
<?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> SpringJMS</display-name> <servlet> <description> </description> <display-name> InvoiceSenderServlet</display-name> <servlet-name>InvoiceSenderServlet</servlet-name> <servlet-class> jms.InvoiceSenderServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>InvoiceSenderServlet</servlet-name> <url-pattern>/InvoiceSenderServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <listener> <listener-class>org.springframework.web.context. ContextLoaderListener</listener-class> </listener> </web-app>Step 9:
Run the servlet and check the console.
Conclusion
Spring JMS API is used to achieve asynchronous communication. The bean configuration file plays very important role because all the resources required for JMS is configured inside xml file. The MOM is acting as a mediator between the sender and receiver. Weblogic MOM supports many features for JMS.
also read:
Once the programmers start using Spring in JMS applications, they will appreciate its simplicity for asynchronous messaging. The Spring JMS framework provides a variety of Java classes to implement JMS applications.
Hope this article will be useful for beginners to write JMS applications using Spring and Web logic.