I don't know much about spring...
But this doesn't make anything:
<bean id="destination" class="org.hornetq.jms.client.HornetQTopic">
<constructor-arg name="name" value="test" />
It just creates an Object of hornetQTopic, but it doesn't actualy create a phisical topic. You should either use createTopic on server controls methods or use the configuration.
I know this only creates a Topic object. this is what I need. I created the real topic using the hornetq config file. However, I fear that the topic is not persistent hence does not support durablity.
All you need is to make sure you use Persistence, and the Journal. And that you create your subscriptions (or queues) as durable.
Believe it or not <property name="subscriptionDurable" value="true" /> does absolutely nothing in DefaultMessageListenerContainer.
First make sure jms is configured to give permission to allow durable subscription to be created.
<permission type="createNonDurableQueue" roles="guest"/>
<permission type="deleteNonDurableQueue" roles="guest"/>
<permission type="createDurableQueue" roles="guest"/>
<permission type="deleteDurableQueue" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="send" roles="guest"/>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/ConnectionFactory" />
<bean id="durableConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="clientId" ref="hostIpAddress" />
this client id here must be unique for each subscriber, i use server ip address, assuming one subscriber per server.
<bean id="topicListenContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="durableConnectionFactory"/>
<property name="destination" ref="someTopic"/>
<property name="pubSubDomain" value="true" />
<property name="subscriptionDurable" value="true" />
<property name="durableSubscriptionName" value="SomeTopicSubscription" />
<property name="messageListener" ref="jmsTopicMessageHandler" />
<property name="concurrentConsumers" value="1" />
<property name="taskExecutor" ref="staticPoolExecutor" />
this should work, oh yeah subscriptionDurable here just use by listener container to do configuration validation check. So if you have say concurrentConsumers greater than one with subscriptionDurable set to true it will throw exception on startup.
Also the connection factory here cannot be picked up by java:/JmsXA that can be used for sending and listen by MDB but cannot be used by DefaultMessageListenerContainer for reading, use java:/XAConnectionFactory.
Thanks Frank for your great answer. one small things that puzzles me. Why do we need both the clientId and the "durableSubscriptionName"?
I believe the client id is tied to the connection, and each connection can have multiple durable subscribers. So it is more like a combination of clientId/Subscription name that uniquely identified by the server.