Spring Framework : A Framework from SpringSource :: Spring with JMS(Java Message Service)
- Spring with JMS Introduction?
- JMS Packages in Spring
- Using Spring JMS
- Sending a Message
- Receiving a message
- Download Examples
Spring with JMS Introduction? |
Spring provides a JMS integration framework that simplifies the use of the JMS API.
JMS can be roughly divided into two areas of functionality, namely the production and consumption of messages. The JmsTemplate class is used for message production and synchronous message reception. For asynchronous reception similar to J2EE’s message-driven bean style, Spring provides a number of message listener containers that are used to create Message-Driven POJOs (MDPs).
JMS 1.0.2 defined two types of messaging domains, point-to-point (Queues) and publish/subscribe (Topics).
As an example of a functional difference that was removed, if you use a JMS 1.1 provider you can transactionally consume a message from one domain and produce a message on the other using the same Session.
Note : The JMS 1.1 specification was released in April 2002 and incorporated as part of J2EE 1.4 in November 2003.
JMS Packages in Spring |
- The package org.springframework.jms.core – provides the core functionality for using JMS. It contains JMS template classes that simplifies the use of the JMS by handling the creation and release of resources, much like the JdbcTemplate does for JDBC.
- The package org.springframework.jms.support – provides JMSException translation functionality. The translation converts the checked JMSException hierarchy to a mirrored hierarchy of unchecked exceptions.
- The package org.springframework.jms.support.converter – provides a MessageConverter abstraction to convert between Java objects and JMS messages.
- The package org.springframework.jms.support.destination – provides various strategies for managing JMS destinations, such as providing a service locator for destinations stored in JNDI.
- Finally, the package org.springframework.jms.connection – provides an implementation of the ConnectionFactory suitable for use in standalone applications. It also contains an implementation of Spring’s PlatformTransactionManager for JMS (the cunningly named JmsTransactionManager). This allows for seamless integration of JMS as a transactional resource into Spring’s transaction management mechanisms
Using Spring JMS |
JmsTemplate
The JmsTemplate only needs to implement callback interfaces giving them a clearly defined contract. The MessageCreator callback interface creates a message given a Session provided by the calling code in JmsTemplate. In order 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.
The JMS API exposes two types of send methods, one that takes delivery mode, priority, and time-to-live as Quality of Service (QOS) parameters and one that takes no QOS parameters which uses default values. Since there are many send methods in JmsTemplate, the setting of the QOS parameters have been exposed as bean properties to avoid duplication in the number of send methods. Similarly, the timeout value for synchronous receive calls is set using the property setReceiveTimeout.
Some JMS providers allow the setting of default QOS values administratively through the configuration of the ConnectionFactory. This has the effect that a call to MessageProducer’s send method send(Destination destination, Message message) will use different QOS default values than those specified in the JMS specification. In order to provide consistent management of QOS values, the JmsTemplate must therefore be specifically enabled to use its own QOS values by setting the boolean property isExplicitQosEnabled to true.
Note : Instances of the JmsTemplate class are thread-safe once configured. This is important because it means that you can configure a single instance of a JmsTemplate and then safely inject this shared reference into multiple collaborators. To be clear, the JmsTemplate is stateful, in that it maintains a reference to a ConnectionFactory, but this state is not conversational state.
Connections
The JmsTemplate requires a reference to a ConnectionFactory. The ConnectionFactory is part of the JMS specification and serves as the entry point for working with JMS. It is used by the client application as a factory to create connections with the JMS provider and encapsulates various configuration parameters, many of which are vendor specific such as SSL configuration options.
Spring provides an implementation of the ConnectionFactory interface, SingleConnectionFactory, that will return the same Connection on all createConnection calls and ignore calls to close.
Destination Management
Destinations, like ConnectionFactories, are JMS administered objects that can be stored and retrieved in JNDI. When configuring a Spring application context you can use the JNDI factory class JndiObjectFactoryBean to perform dependency injection on your object’s references to JMS destinations.
You can also configure the JmsTemplate with a default destination via the property defaultDestination. The default destination will be used with send and receive operations that do not refer to a specific destination.
Message Listener Containers
One of the most common uses of JMS messages in the EJB world is to drive message-driven beans (MDBs). Spring offers a solution to create message-driven POJOs (MDPs) in a way that does not tie a user to an EJB container.
A message listener container is used to receive messages from a JMS message queue and drive the MessageListener that is injected into it. The listener container is responsible for all threading of message reception and dispatches into the listener for processing.
There are three standard JMS message listener containers packaged with Spring, each with its specialised feature set.
-
SimpleMessageListenerContainer
It simply creates a fixed number of JMS sessions at startup and uses them throughout the lifespan of the container. - DefaultMessageListenerContainer In contrast to SimpleMessageListenerContainer, this container variant does allow for dynamic adaption to runtime demands and is able to participate in externally managed transactions.
- ServerSessionMessageListenerContainer This listener container leverages the JMS ServerSessionPool SPI to allow for dynamic management of JMS sessions.If there is no need for provider-driven runtime tuning, look at the DefaultMessageListenerContainer or the SimpleMessageListenerContainer instead.
Transaction management
Spring provides a JmsTransactionManager that manages transactions for a single JMS ConnectionFactory. The JmsTransactionManager performs local resource transactions, binding a JMS Connection/Session pair from the specified ConnectionFactory to the thread. JmsTemplate automatically detects such transactional resources and operates on them accordingly.
Sending a Message |
Sending a Message
The JmsTemplate contains many convenience methods to send a message.
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.JmsTemplate102;
public class JmsQueueSender {
private JmsTemplate jmsTemplate;
private Queue queue;
public void setConnectionFactory(ConnectionFactory cf) {
this.jmsTemplate = new JmsTemplate102(cf, false);
}
public void setQueue(Queue queue) {
this.queue = queue;
}
public void simpleSend() {
this.jmsTemplate.send(this.queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("Hi, I am James Bond for Queue.");
}
});
}
}
This example uses the MessageCreator callback to create a text message from the supplied Session object and the JmsTemplate is constructed by passing a reference to a ConnectionFactory and a boolean specifying the messaging domain.
A zero argument constructor and connectionFactory / queue bean properties are provided and can be used for constructing the instance (using a BeanFactory or plain Java code).
Alternatively, consider deriving from Spring’s JmsGatewaySupport convenience base class, which provides pre-built bean properties for JMS configuration.
Using Message Converters
The JmsTemplate has various send methods that take a Java object as an argument for a message’s data content. The overloaded methods convertAndSend and receiveAndConvert in JmsTemplate delegate the conversion process to an instance of the MessageConverter interface. This interface defines a simple contract to convert between Java objects and JMS messages. The default implementation SimpleMessageConverter supports conversion between String and TextMessage, byte[] and BytesMesssage, and java.util.Map and MapMessage.
The example below demonstrates how to modify a message header and a property after a java.util.Map is converted to a message.
public void sendWithConversion() {
Map map = new HashMap();
map.put("Name", "Smith");
map.put("Age", new Integer(45));
jmsTemplate.convertAndSend("testQueue", map, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setIntProperty("AccountID", 12345);
message.setJMSCorrelationID("123-00001");
return message;
}
});
}
This results in a message of the form:
MapMessage={
Header={
... standard headers ...
CorrelationID={123-00001}
}
Properties={
AccountID={Integer:12345}
}
Fields={
Name={String:Smith}
Age={Integer:45}
}
}
SessionCallback and ProducerCallback
While the send operations cover many common usage scenarios, there are cases when you want to perform multiple operations on a JMS Session or MessageProducer. The SessionCallback and ProducerCallback expose the JMS Session and Session / MessageProducer pair respectfully. The execute() methods on JmsTemplate execute these callback methods.
Receiving a message |
Receiving a message
Synchronous Reception
While JMS is typically associated with asynchronous processing, it is possible to consume messages synchronously. The overloaded receive(..) methods provide this functionality. During a synchronous receive, the calling thread blocks until a message becomes available. This can be a dangerous operation since the calling thread can potentially be blocked indefinitely. The property receiveTimeout specifies how long the receiver should wait before giving up waiting for a message.
Asynchronous Reception – Message-Driven POJOs
In a fashion similar to a Message-Driven Bean (MDB) in the EJB world, the Message-Driven POJO (MDP) acts as a receiver for JMS messages. The one restriction on an MDP is that it must implement the javax.jms.MessageListener interface. Please also be aware that in the case where your POJO will be receiving messages on multiple threads, it is important to ensure that your implementation is thread-safe.Below is a simple implementation of an MDP:
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class ExampleListener implements MessageListener {
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
Once you’ve implemented your MessageListener, it’s time to create a message listener container.
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="jmsexample.ExampleListener" />
<!-- and this is the message listener container -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener" />
</bean>
The SessionAwareMessageListener interface
The SessionAwareMessageListener interface is a Spring-specific interface that provides a similar contract the JMS MessageListener interface, but also provides the message handling method with access to the JMS Session from which the Message was received.
Click Below to download the Examples
Hello I am so glad I found your blog, I really found you by mistake, while I was browsing on Digg for something else, Anyhow I am here now and would just like to say kudos for a incredible post and a all round exciting blog (I also love the theme/design), I don’t have time to browse it all at the minute but I have book-marked it and also added in your RSS feeds, so when I have time I will be back to read a great deal more, Please do keep up the fantastic work.