I need to ensure redelivery of JMS messages when the consumer fails, but the strategies accepted on similar questions here might not apply to my case.
Consider a JMS client - spring + activeMq - receiving messages, which cannot be lost or duplicated. Because the processing of the messages is expensive, the client batch them. The scenario plays as below:
- T1 - Client receives messages A, B, C and D
- T2 - A thread wakes up on the client and decides to handle messages A, B and C
- T3 - Client receives messages E and F
- T4 - The thread returns having processed A, B and C. It can then pick up the next batch if another thread has not done so already.
The way the producer is set up now - DefaultJmsListenerContainerFactory and Session.AUTO_ACKNOWLEDGE - messages are removed as soon as they are delivered, whether they have been picked up by a thread or not. If the client goes down just before T4 , messages A to F are lost.
I was planning to use Session.CLIENT_ACKNOWLEDGE on the producer and get each thread to call msg.acknowledge() after T4, but according to the documentation, this will also acknowledge E and F, which will be lost if the client fails after T4.
I am not convinced a transacted session will help here either, as it would cover messages A to F, while a thread completion only guaranties a subset of this has been processed.
My objective is to have a guarantee that in case of a failure of the client, e.g. the VM goes down, all the messages in flight that have not been successfully handled by a thread remains in the topic/queue. They can then be picked up by the client when it comes back up.
Any idea on how I can achieve this ?
S