Thursday, July 2, 2009

Persistent JMS Topics using ActiveMQ and Spring

At work we noticed that a messaging application based on Topics was loosing pending messages after a restart of ActiveMQ. It turns out we were not using Durable Topic Subscribers. To configure these add this to your Spring Listener configuration:
<bean id="myListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <!-- never use concurrentConsumers with topics ! -->
    <property name="concurrentConsumers" value="1">
    <property name="connectionFactory" ref="jmsActiveMQFactory">
    <property name="destination" ref="myTopic">
    <property name="messageListener" ref="myMessageListener">
    <property name="sessionTransacted" value="true">
    <!-- Specify topic style publish/subscribe -->
    <property name="pubSubDomain" value="true">
    <!-- Will guaranty that we receive messages in queue after broker goes down -->
     <property name="subscriptionDurable" value="true">
     <property name="clientId" value="myApp">
     <property name="durableSubscriptionName" value="myApp">
</bean>


Both the durableSubscriptionName and clientId are required.

Also, you should ensure the JmsTemplate is configured to persistent delivery mode (this is the default):
<bean id="jmsActiveMQTemplate" class="org.springframework.jms.core.JmsTemplate">
     <property name="connectionFactory" ref="jmsActiveMQFactory">

     <!-- Value = javax.jms.DeliveryMode.PERSISTENT -->
     <property name="deliveryMode" value="2">

     <!-- Value = javax.jms.Session.CLIENT_ACKNOWLEDGE -->
     <property name="sessionAcknowledgeMode" value="2">

     <!-- Needs to be true for the deliveryMode to work -->
     <property name="explicitQosEnabled" value="true">
</bean>


To check if your Topic Subscribers are durable you can use the ActiveMQ web admin interface, your application should be listed under 'Subscribers'.