This probably affects much later versions of Spring as well, but I haven't confirmed it yet (looks that way from comparing this class with the 4.0.4 release).
configure your listener container for CLIENT_ACKNOWLEDGE acknoledgement mode, and CACHE_CONSUMER level caching.
use a shared JMS connection (may not be required)
call stop() on the DMLC when the listener container is in a javax.jms.MessageConsumer#receive() call.
If the receive() call returns with a message, the AbstractMessageLIstenerContainer#doExecuteListener() method will not process the message. It will throw a MessageRejectedWhileStoppingException which is quietly ignored.
Now call start() The next message from the JMS destination is received and if processed successfully, is acknowledged. This acknowledges all previously received messages...including the one that was rejected. Thus, the rejected message is never redelivered, even though it was never processed.
It seems like, when rejecting the message, recover should be called on the JMS session. This would cause the message to be redelivered.
A work-around is to call AbstractMessageListenerContainer#setAcceptMessagesWhileStopping(true); which prevents the message from being initially rejected.
This problem was seen in a production application using Tibco, but I don't believe the problem is provider specific.
#17644 Remoting over JMS with receiveTimeout blocks service forever
#17869 Doc: Clarify AUTO_ACKNOWLEDGE semantics with SimpleMessageListenerContainer