Configuring durable messages with SpringFramework

In our project we have a webservice that receives a message, processes it and sends a response back. Very common for a webservice I think🙂
Now there was an extra request: log all messages in a database so we could get management info out of it, like in which hour of the day are we receiving the most messages, who is sending the most messages that are leading to errors, etc. In this post I will show you how I implemented this request. To have it working with the least impact on our ‘production’ system I chose to put the incoming message in a queue (actually it is a Topic). Then register a MessageListener that will pick up the posted message and log it in a separate database, along with some metadata. The reason I chose a Topic is that I expect to have more requests in the future to do something with the incoming message. By using a Topic I can just add a receiver and have that handle the new request.

We have the following Application Server setup:

  • JBoss 4.0.5GA
  • JBoss Messaging 1.2SP1

To define the Topic in JBoss Messaging I added the following section to ‘destinations-service.xml’:

<mbean code="org.jboss.jms.server.destination.TopicService"
    <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    <attribute name="DLQ">jboss.messaging.destination:service=Queue,name=DLQ</attribute>
    <attribute name="ExpiryQueue">jboss.messaging.destination:service=Queue,name=ExpiryQueue</attribute>

Since sending a message to a Topic is pretty straightforward I will only show how to configure the receiver. I first made the Java class which acts as receiver:

package net.pascalalma.logger;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;

import net.pascalalma.model.LogMelding;
import net.pascalalma.exceptions.StatisticsException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LoggerBean implements MessageListener {

   private static final Log LOG = LogFactory.getLog(LoggerBean.class);

   public void onMessage(Message msg) {"onMessage(Message msg)");

      if (msg instanceof ObjectMessage) {

         ObjectMessage om = (ObjectMessage)msg;
         try {
            if ( om.getObject() instanceof LogMelding) {
               LogMelding lm = (LogMelding)((ObjectMessage)msg).getObject();

     "LogMelding in Topic = " + lm);
            } else {
               throw new IllegalArgumentException("Only instances of LogMelding may be put in this Topic.");
         } catch (JMSException je) {
            throw new StatisticsException(je);
      } else {
         throw new IllegalArgumentException("Only ObjectMessages may be put in this Topic.");

Next we have to configure this MessageListener implementation in Spring. Here is my application-context:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans SYSTEM "../dtd/spring-beans.dtd">
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">

  <!--  JNDI properties -->
  <bean id="jndiTemplate"
    <property name="environment">
        <prop key="java.naming.factory.initial">
        <prop key="java.naming.provider.url">
        <prop key="java.naming.factory.url.pkgs">

  <!--  JNDI Connection Factory -->
  <bean id="jmsConnectionFactory"
    <property name="targetConnectionFactory">
        <property name="jndiTemplate" ref="jndiTemplate" />
        <property name="jndiName" value="myConnectionFactory" />
    <property name="clientId" value="clientID"/>
  <!--  Destination for the incoming messages -->
  <bean id="myMessageTopic"
    <property name="jndiTemplate">
      <ref bean="jndiTemplate" />
    <property name="jndiName" value="${queue.log}" />

  <!-- The messageListenerContainer -->
  <bean id="myMsgTopiclistener"
    <property name="concurrentConsumers" value="1" />
    <property name="maxConcurrentConsumers" value="1" />
    <property name="connectionFactory" ref="jmsConnectionFactory" />
    <property name="sessionTransacted" value="true" />
    <property name="destination" ref="myMessageTopic" />
    <property name="messageListener" ref="loggerBean" />
    <property name="subscriptionDurable" value="true"/>
    <property name="durableSubscriptionName" value="myMsgTopiclistener"/>

   <!-- === Business Layer === -->
   <bean id="loggerBeanOriginal" class="net.pascalalma.logger.LoggerBean" />

   <!--  Business Layer Service is transactional -->
   <bean id="loggerBean" parent="txProxyParent">
      <property name="target" ref="loggerBeanOriginal" />

The difference with the non-durable configuration is the property ClientId at the jmsConnectionFactory bean:

<property name="clientId" value="clientID"/>

And the following properties at the myMsgTopiclistener bean:

  <property name="subscriptionDurable" value="true"/>
  <property name="durableSubscriptionName" value="myMsgTopiclistener"/>

If you leave these properties out you will have the non-durable variant of the message listener.

So here is another proof that Spring can make your life as developer a lot easier🙂

About Pascal Alma

Pascal is a senior software developer and architect. Pascal has been designing and building applications since 2001. He is particularly interested in Open Source toolstack (Mule, Spring Framework, JBoss) and technologies like Web Services, SOA and Cloud technologies. Lately he is having great fun by building iOS apps with Swift. Specialties: JEE AWS XML/XSD/XSLT Web Services/SOA Mule ESB/ WSO2 ESB Maven Cloud Technology Swift/ iOS
This entry was posted in JMS, Spring Framework and tagged , , . Bookmark the permalink.