I am trying to manage a JMS transaction using Spring and HornetQ.
This is the code I wrote:
public void receive() { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); Message msg = jmsTemplate.receive(queue); boolean success = false; if (msg != null) { try { success = handleMessage(msg); if (success) { msg.acknowledge();
I am doing synchronous reading from a queue, with a timeout of 0, since I do not want to block reading. Because of this, I have to check if something was really received.
This is an excerpt from my applicationContext.xml :
<bean id="inVMConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>java:/ConnectionFactory</value> </property> </bean> <bean id="cachedConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <property name="targetConnectionFactory" ref="inVMConnectionFactory" /> </bean> <bean id="producer" class="it.ubiquity.gestoreprofilazione.onweb.OnWebProducer" scope="singleton"> <property name="queue" ref="retryQueue" /> <property name="connectionFactory" ref="cachedConnectionFactory" /> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="cachedConnectionFactory" /> <property name="sessionTransacted" value="true" /> <property name="sessionAcknowledgeMode" value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}" /> <property name="pubSubDomain" value="false" /> <property name="receiveTimeout" value="# {T(org.springframework.jms.core.JmsTemplate).RECEIVE_TIMEOUT_NO_WAIT}" /> </bean> <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager"> <property name="connectionFactory" ref="cachedConnectionFactory" /> </bean> <bean id="consumer" class="it.ubiquity.gestoreprofilazione.onweb.OnWebConsumer" scope="singleton"> <property name="queue" ref="retryQueue" /> <property name="jmsTemplate" ref="jmsTemplate" /> <property name="transactionManager" ref="jmsTransactionManager" /> </bean>
My problem is rather strange: the first time I get a message, handleMessage fails, so I roll back the transaction. Then nothing else happens. If I check using the JMX console, I see there is one message in the queue. Now, if I restart JBoss, the messages will be received again and again, as expected.
There may be something wrong with my configuration, but why does it work after a reboot?
- HornetQ 2.2.10
- JBoss 5.1.0
- Spring 3.1.2
UPDATE
With debugging enabled, I see the first time:
DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Create a new transaction named [null]: PROPAGATION_REQUIRED, ISOLATION_DEFAULT
and after the first rollback with subsequent reception and rollback, I see:
DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Participation in an existing transaction
Instead, after restarting JBoss, I read that the transaction is actually rollback:
DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Initiation of a transactional rollback 2012-11-05 09:54:14,436 DEBUG [Org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) JMS transaction rollback in session
So, why the rollback does not happen the first time, and as soon as I restart the server, it happens all the time? What am I doing wrong?