Dec 10th, 2010, 04:50 PM
Ack back to RabbitMQ after an error occurs
I am using rabbit mq with spring integration using the SimpleMessageListenerContainer and a custom error handler.
When using transactions the message will be retrieved from the from queue then an error occurs that cannot be recovered from. I want to get the next message and continue processing. The problem is that if there is an exception thrown we end up in the error channel with no way to ack the message.
More over in the code that errors we cannot ack and then throw an exception either.
So we are not able to retrieve the next message since we are still in the transaction.
It seems that the only way to ack is if we not throw an exception into the channel and that negates the value of the errorChannel.
If possible I would like to be able to explicitly ack somewhere on the normal or error path.
Any help would greatly appreciated.
<bean id="errorHandler" class="com.company.ProcessingErrorHandler">
<property name="typeDao" ref="typeDao" />
<property name="detailDao" ref="detailDao" />
<si:service-activator input-channel="errorChannel" ref="errorHandler" method="handleError"/>
Dec 11th, 2010, 02:20 AM
Is there a reason you don't just use auto-ack? If the exception is not going to cause a rollback, then what value do you get from a transaction?
Having said that, there was another question recently about manual acks in another thread (can't find it now - maybe on the rabbit-discuss list). I am interested in at least doing some analysis to find out what drives this. It's not a very common pattern with Spring outside AMQP, so maybe this is a feature of AMQP that adds some value and we can use that as an argument in favour. If someone opens a JIRA, we can look at it in more detail.
Dec 13th, 2010, 11:42 AM
Thanks for the reply. I need to control the ack since I dont want to loose a message if for example our machine goes down while processing a message.
Dec 21st, 2010, 01:58 PM
In my case, I have the need to manually ack messages because I'm using basicReject to acknowledge certain message that my consumer sees. This consumer for various reasons requires the flexibility to dispose of the messages with either basicAck, basicReject(deliveryTag, true) -- requeue, or basicReject(deliveryTag, false) -- don't requeue (and in the future send to the dead-letter exchange).
With the current SimpleMessageListenerContainer, I can either auto-ack or use the simple (albeit reasonable) strategy that SimpleMessageListenerContainer provides which appears to boil down to "ack if no exception was thrown". If I try to call basicAck or basicReject myself from my ChannelAwareMessageListener, things will eventually go awry because the broker won't accept multiple acknowledgements for the same delivery tag.
It would be nice to have a little more flexibility by providing an "acknowledgementStrategy" enum property (e.g. AUTO, SIMPLE, MANUAL) instead of just an "autoAck" boolean property, so that I wouldn't have to implement my own MessageListenerContainer which otherwise does the same thing as the SimpleMessageListenerContainer
Dec 30th, 2010, 03:34 AM
A few people have asked for manual acks in the MLC recently. It's not tested (so not necessarily supported yet). If you look at JIRA and don't find anything relevant you could open a new ticket. Code contributions are also welcome.
Note that the recent 1.0.0.M2 release has a different auto-ack configuration strategy (but still not the enum that you are looking for).