Search code examples
springspring-jmsjmstemplate

Stop a spring jms message listener


I have a scenario where i need to stop the spring's DefaultMessageListenerContainer and then later start that again. I have 10 different DefaultMessageListenerContainer listening to 10 different queue. All 10 different containers are calling the same method of same message listener class. Now i want to stop the messagelistenercontainer for a particular queue depending on the exception i get in onMessage method. Please suggest me how i can achieve the above scenario.

Below is my listener configuration

<bean id="msglistenerForAuditError" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsFactory"/>
        <property name="sessionTransacted" value="true"/>
        <property name="destinationName" value="test.audit.error2"/>
        <property name="messageListener" ref="auditerrorListener" />
    </bean>

    <bean id="msglistenerForAuditEvent" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsFactory"/>
        <property name="sessionTransacted" value="true"/>
        <property name="destinationName" value="test.audit.event2"/>
        <property name="messageListener" ref="auditerrorListener" />
    </bean>

Solution

  • The DefaultMessageListenerContainer is a lifecycle bean and as such it exposes a start and a stop method that you can use to start and stop the listener, respectively.

    You can build a service on your own that is gathering all known instances in the context and you can then loop over those to stop the containers, something like

    @Service
    public class MyService {
    
        private final Collection<DefaultMessageListenerContainer> containers;
    
        @Autowired
        public MyService(Collection<DefaultMessageListenerContainer> containers) {
            this.containers = containers;
        }
    
        public void stopAll() {
            // iterate over the collection and call "stop()" on each item
        }
    }
    

    That being said:

    1. You should not invoke this service as part of a message listener as attempting to stop the container while the thread is processing a message will have weird side effect
    2. The whole use case looks suspicious to me. Your message listeners should be resilient and, more importantly, they should be independent of each other; if you are stopping listener A because listener B threw an exception, something is definitely wrong in your design