synchronous JMS messaging with Spring …
Saturday, November 10th, 2007My current work involves messaging and I have been working with Spring and JMS (ActiveMQ), which is a great combination, especially since you can make Message Driven Pojos (MDP).
In most cases I try to make interactions between components asynchronous, where a request is sent and a response is not immediately expected, but dealt with later, possibly by another component. However, there are situations where this isn’t desired and you need to be able to send a request and wait for the response before continuing.
Spring provides an excellent facility for this with it’s JMS remoting, but in my case I couldn’t use this because non-spring based components need to send requests. I didn’t find a way to achieve this out of the box with Spring so I had to write something to do the job. This is the code:
public Object convertAndSendAndReceiveAndConvert(Object request) {
final String uuid = UUID.randomUUID().toString();
convertAndSend(request, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setJMSCorrelationID(uuid);
return message;
}
});
return receiveSelectedAndConvert(getReplyFromDestination(),
"JMSCorrelationID='" + uuid + "'");
}
I put this code into my own subclass of JmsTemplate so the calling code can just call convertAndSendAndReceiveAndConvert(). I also added some properties to the JmsTemplate subclass to define the reply queue. The Spring definition of the template looks like this:
(I’m wrestling with my blog editor and have removed some XML characters, but I’m sure you get the gist.)
bean id="doSomethingSynchronousJmsTemplate" class="MyJmsTemplate"
property name="connectionFactory" ref="connectionFactory"
property name="defaultDestination" ref="requestQueue"
property name="replyFromDestination" ref="replyQueue"
property name="messageConverter" ref="xmlMessageConverter"
property name="receiveTimeout" value="5"
I’m using a queue for requests and a queue for responses which “feels” right when considered against a temporary queue for this situation.
The calling code is much the same as other JmsTemplate usages:
return (reply) _synchronousJmsTemplate
.convertAndSendAndReceiveAndConvert(request);
I’m converting the Request and Response objects using XStream in a custom MessageConverter subclass. This allows the receiving components to accept XML requests from any sender. As long as they conform the the XML wire format.
All is working nicely, and I hope this post helps you.