Spring Series Tutorial – Spring JMS
In this fourth and final installment of the Spring Series , I introduce you to features of the Spring JMS (Java Message Service) framework. JMS defines a standard way for Java applications to create and exchange messages through a Message Oriented Middleware (MOM).
As in the previous articles of this series, I use a simple example to demonstrate the features of Spring JMS. You’ll follow along as I develop a point to point (P2P) message-based system, using the Spring JMS framework to integrate with IBM’s WebSphere MQ through a JMS Interface. Upon completing the exercise, you’ll be able to send and receive simple text messages through the system.
Download the article source before you begin. The examples was tested on IBM WebSphere MQ 5.3. You will also need Apache Ant to run the example application.
Spring’s JMS abstraction framework simplifies the use of JMS APIs and smoothly integrates with JMS providers such as IBM’s WebSphere MQ 5.3. The package org.springframework.jms.core provides the core functionality for using JMS in Spring. Its template classes simplify the use of the JMS by handling the creation and release of resources.
Like most other Spring template classes, the JMS template classes provide helper methods that perform common operations. In cases that require more sophisticated usage, the classes delegate the essence of the processing task to user-implemented callback interfaces. The JMS classes offer convenience methods for sending a message, consuming a message synchronously, and exposing a JMS session and message producer to the user.
Along with org.springframework.jms.core, the following JMS packages comprise Spring JMS functionality:
- Provides functionality to translate JMSExceptions. The translation code converts the checked JMSException hierarchy to a mirrored hierarchy of unchecked exceptions.
- Provides a MessageConverter abstraction to convert between Java objects and JMS messages.
- Provides various strategies for managing JMS destinations, such as a service locator for destinations stored in JNDI.
- Provides an implementation of the ConnectionFactory suitable for use in standalone applications. The connection package also contains an implementation of Spring’s PlatformTransactionManager for JMS. This allows for the integration of JMS as a transactional resource into Spring’s transaction management mechanisms.
As previously mentioned, the example application will use the Spring JMS framework to integrate with IBM’s WebSphere MQ through a JMS Interface. WebSphere MQ provides reliable, resilient application integration by passing messages between applications and Web services. It uses queuing and transactional facilities to help preserve the integrity of messages across the network. WebSphere MQ reduces the risk of information loss and the need to reconcile communicating IT systems.
WebSphere MQ provides a consistent application programming interface (MQI) across all its supported platforms, which helps make integrated programs portable. In addition to its standard interface, WebSphere MQ also fully implements the JMS interface, including support for publish-and-subscribe messaging. The WebSphere MQ Explorer tool enables the entire MQ network to be administered and configured remotely. The administration and configuration tool is based on the open source Eclipse framework and is extensible.
The Spring framework provides two implementations of the JmsTemplate. The class JmsTemplate uses the JMS 1.1 API and the subclass JmsTemplate102 uses the JMS 1.0.2 API. My example application uses the JmsTemplate102.
The JMS template is used to send and receive JMS messages. Spring employs a callback mechanism to coordinate JMS messaging. The MessageCreator callback interface creates a message given a Session provided by the calling code in JmsTemplate. To allow for more complex usage of the JMS API, the callback SessionCallback provides the user with the JMS session and the callback ProducerCallback exposes a Session and MessageProducer pair.
Listing 1 shows the configuration of the JMS template used for the example application. The listing is an extract from the spring-mqseries-jms.xml file.
Listing 1. JMS template configuration
|<!– JMS Queue Template –>
The jmsQueueTemplate bean is wired with a JMS connection factory and a JMS destination resolver for resolving destination queue names supplied by JMS clients through JNDI. The connectionFactory property specifies how to get a connection to a JMS provider. In the case of the example, Listing 2 shows how to retrieve the connection factory from JNDI.
Listing 2. Configuring a JMS connection factory through JNDI
|<!– JMS Queue Connection Factory –>
As you can see, the JndiObjectFactoryBean is wired to an internalJmsQueueConnectionFactory. The JndiObjectFactoryBean uses the JndiTemplate property for JNDI lookup. Spring will look up the connection factory in JNDI using the environment property and initial context specified in the JndiTemplate. Listing 3 shows the configuration of the JndiTemplate configuration bean.
Listing 3. JNDI template configuration for JNDI lookup
The above configuration specifies the initial context factory as com.sun.jndi.fscontext.RefFSContextFactory and the provider URL as the file-based file:/C:/JNDI-Directory for JNDI lookup. For the purpose of the example application, the JNDI access will use the file-based FSContext version configured for binding MQ queues to JNDI.
With the JMS template defined, the next step is to wire it into the example application, after which you can use it to send and receive messages.
The JMS template can be wired into an application to send and receive JMS messages. In Listing 4 you can see how I wired the JMS template from Listing 1 into my example application.
Listing 4. Wiring JmsTemplate into an application
As you can see, I wired jmsQueueTemplate into both the JmsSender application bean and the JmsReceiver bean used to send and receive messages. Listing 5 shows relevant code for the JMSSender class.
Listing 5. JMSSender using JmsTemplate to send JMS messages
and comment out the remaining two INITIAL_CONTEXT_FACTORY variables. Also uncomment the following line:
and comment out the remaining two PROVIDER_URL variables.
You’ll find a sample configuration file provided for reference in the C:\SpringSeriesPart4JMS\batch folder.
To store JNDI objects, make a directory named JNDI-Directory on your C: drive. Switch over to the \MQSeriesInstallableDirectory\Java\bin directory and run the JMSAdmin batch file and you should see the the InitCtx variable.
Type in the following, one after the other:
|> ant -f build-jmssender.xml.|
This will build and run the SendMQSpringJMS class, which calls the JMSSender class for sending a text message to the WebSphere MQ RequestResponse queue. SendMQSpringJMS also loads the spring configuration files through its ClassPathXmlApplicationContext. Once the beans are loaded, JMSSender can be accessed through the Spring ApplicationContext getBean() method (see Listing 7).
Listing 7. Loading the Spring configuration for the example application
|> ant -f build-jmsreceiver.xml|
This will build and run the ReceiveMQSpringJMS class, which calls the JMSReceiver class to receive a text message from the WebSphere MQ RequestResponse queue. The following message prints at the console:
|Message Received –> This is a sample message.|
In this final article in the Spring series, you learned the fundamentals of the Spring JMS framework. I first introduced the essential components of the example application — the Spring JMS framework and IBM’s WebSphere MQ 5.3 — then showed you how to use a Spring JMS templates to send and receive messages from the WebSphere MQ queue. While the example is very simple, you can apply the outlined steps to applications of greater complexity.
I hope this series introducing the essential modules of the Spring framework has been useful to you. The Spring series was written on Spring framework 1.0 release in June 2005. This article of mine was first published by IBM DeveloperWorks. All rights retained by IBM and the author.