Skip to content

Publishing QoS (Priority) Enabled Messages using Spring JMS Template

April 27, 2010

For me Spring’s JMS API is one of the mostly loved ones because of its brilliant design. At the past I always coded JMS for myself and there where always on and off issues regarding pooling, reconnection, transaction, performance etc but after I switched to Spring JMS the are all history now.

But besides great features, unfortunately there are still some features missing there. One is lack of proper setting of QoS attributes in the JMS message. In fact JmsTemplate does work when you want to set a predefined value for every message, but this is not usually the case in real applications and you may decide to set QoS (TTL, Priority, etc) based on message content, and destinations.

You may find more info regarding this in these Jira and forum posts: https://jira.springsource.org/browse/SPR-5183
http://forum.springsource.org/showthread.php?p=295937

BTW This issue is still available in Spring 3.0. Here is a very simple solution:

package com.magfa.common.submit.async.jms;

import org.springframework.jms.core.JmsTemplate;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;

/**
* User: amin
* Fixes Spring JmsTemplate issue regarding per-message QoS 
* see: https://jira.springsource.org/browse/SPR-5183
* see: http://forum.springsource.org/showthread.php?p=295937
*/
public class QoSEnabledJmsTemplate extends JmsTemplate {
   protected void doSend(MessageProducer producer, Message message) throws JMSException {
      producer.send(message, getDeliveryMode(), message.getJMSPriority(), getTimeToLive());
   }
}

And then every where you want to use JmsTemplate for publishing set JMSPriority manually and use this template:

    <bean id="dlrQueuePub" class="com.magfa.common.submit.async.jms.SpringJmsTemplateMessagePublisher">
        <constructor-arg>
            <bean class="com.magfa.common.submit.async.jms.QoSEnabledJmsTemplate">
                <property name="connectionFactory" ref="cachingConnectionFactory"/>
                <property name="defaultDestinationName" value="dlr"/>
                <property name="deliveryPersistent" value="true"/>
            </bean>
        </constructor-arg>
        <constructor-arg ref="priorityDao"/>
    </bean>

Use a simple MessageCreator class to do this:

private static final MessageConverter converter = new SimpleMessageConverter();

private class GatewayMessageCreator implements org.springframework.jms.core.MessageCreator {

   private final M message;

   private GatewayMessageCreator(M message) {
      this.message = message;
   }

   public javax.jms.Message createMessage(Session session) throws JMSException {
      final javax.jms.Message jmsMsg = converter.toMessage(message, session);

      jmsMsg.setLongProperty("id", message.getId()); jmsMsg.setShortProperty("os",  message.getOrgSrv());

     // note: we may use these properties in query over jms queue if (message.getAccId() != null) {
            jmsMsg.setLongProperty("acc", message.getAccId());
            jmsMsg.setByteProperty("ts", message.getTrmSrv());

            if (message.getTrmSrvConfId() != null)
                 jmsMsg.setLongProperty("tsCfg", message.getTrmSrvConfId());

                 jmsMsg.setJMSPriority(priorityDao.getAccountJmsPriority(message.getAccId())); 
     }
  
     return jmsMsg;
   }
}

Use it like this:

public void publish(M message) throws GatewayException {
   jmsTemplate.send(new GatewayMessageCreator(message)); 
}
Advertisements

From → java

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: