Dovahkiin vas Normandy Dovahkiin vas Normandy - 1 year ago 89
Java Question

Safely Terminating a Spring JMS application

I'm working on a Spring boot JMS application that is setup strictly with bean annotations and is reading messages from WebshpereMQ. Everything works except I can't figure out how to safely shutdown this application. Once my JMSListener Method reads all the messages it just stays idle. I make an initial connection to the queue and access the queue depth, so ideally when queue depth is zero, it needs to wrap it up and shut down. My current workaround (and I do not like it at all) is this little method I call (from inside the listener, yikes) when depth is zero:

public void shutDownApplication() {"Initiating shutdown of application...");
System.out.println("Terminating application...");

I do not like this solution. And neither does Spring, because this is obviously interrupted as an error mid-process and before the application dies my JMSListener initiates a rollback and puts the single last remaining message back on the queue.

I tried a few other solutions after looking at the following sources:

How can I Stop/start/Pause a @JmsListener (the clean way)

How to gracefully shut down a Spring JMS MessageListenerAdapter

This was my most recent solution:

public class JMSShutdownService {

public void initiateShutdown() {
JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry();
Collection<MessageListenerContainer> col = jmsListenerEndpointRegistry
for (MessageListenerContainer cont : col) {


This kills the application but still puts the last message back on the queue. There are alot of intricacies of Spring I'm still trying to understand, so it all really comes down to that. I feel like the main issue is that it is inside the listener I signal for shutdown. From what I gather the listener shouldn't be responsible for that. But I'm not sure how to define a way to shutdown the application before the listener starts, or how to pop out of the listener when queue depth is zero.

Any ideas?

Answer Source
JmsListenerEndpointRegistry jmsListenerEndpointRegistry = new JmsListenerEndpointRegistry();

That's no use; a new registry won't have any containers, if you are using @JmsListener you need to get the registry from the application context.


That just kills the JVM.

The bottom line is you should stop on the container on a different thread - use a task executor to start a new thread to stop the container; the container will wait for the thread to exit the listener before stopping.

After stopping the container, you will need to wait for a grace period before killing the JVM.

How do you really know you are done? Another message could show up after you stop the container, in which case you'll likely see some noise in the log about a message being rejected because the container is stopping.


in my listener...

if (timeToShutDown()) {
    Executors.newSingleThreadExecutor.execute(new Runnable() {

        public void run() {
 // exit the listener so the container can actually stop.