Spring JMS - redelivery by sending message back to same queue instead of rollback transaction

queue, rollback, spring, spring-jms, transactions

Solution

Yes, that is the correct approach.

Problem

this is my first post here so I apologize in advance if I don't respect formatting rules or other general rules. I have a Spring JMS based client application that reads from a queue using multiple consumers. My constraints are: guaranteed redelivery in case of failure and message duplication detection. Spring configuration ``` <bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver" /> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <constructor-arg ref="MyConnectionFactory" /> <property name="destinationResolver" ref="jndiDestinationResolver" /> <property name="receiveTimeout" value="100" /> </bean> <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="destinationResolver" ref="jndiDestinationResolver" /> <property name="connectionFactory" ref="MyConnectionFactory" /> <property name="destinationName" value="my_Queue" /> <property name="messageListener" ref="MyListener" /> <property name="maxConcurrentConsumers" value="10"/> <property name="sessionTransacted" value="true"/> </bean> ``` My listener code is something like: ``` protected void processTextMessage(TextMessage textMessage) { try { // process message } catch(Exception e) { try { sendTextMessage("my_Queue",correlationID, textMessage.getText()); } catch (JMSException e1) { log.error("Error writing message back to the queue!"); throw JmsUtils.convertJmsAccessException(e1); } } } protected void sendTextMessage(String queueName, final byte[] correlationID, String message) { jmsTemplate.convertAndSend(queueName, message, new MessagePostProcessor() { public Message postProcessMessage(Message message) throws JMSException { message.setJMSCorrelationIDAsBytes(correlationID); return message; } }); } ``` I made some local failure tests with ActiveMQ and re-sendings were ok (I noticed the redelivered flag to false). I also tried to stop brutally the application server during processing, and was able to check in that moment queue contained 1 message with redelivered=true. Would this be a right approach to reach my goals? I hope this would be transparent in respect to the JMS provider i will use (on production environents Websphere MQ is used). At the moment I would like to avoid just rollback the transaction by throwing an exception: i wish to reschedule my failed message like a new fresh message in the queue. For duplicate detection, I think inserting a business existence check would be enough. Thanks in advance and best regards

Original source