简体   繁体   English

停止Spring JMS消息监听器

[英]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. 我有一种情况,需要停止弹簧的DefaultMessageListenerContainer,然后再重新启动。 I have 10 different DefaultMessageListenerContainer listening to 10 different queue. 我有10个不同的DefaultMessageListenerContainer,它们侦听10个不同的队列。 All 10 different containers are calling the same method of same message listener class. 所有10个不同的容器都在调用同一消息侦听器类的相同方法。 Now i want to stop the messagelistenercontainer for a particular queue depending on the exception i get in onMessage method. 现在,我想根据onMessage方法中获得的异常,停止特定队列的messagelistenercontainer。 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>

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. DefaultMessageListenerContainer是一个生命周期bean,因此它公开了可以分别用来启动和停止侦听器的startstop方法。

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 如果由于侦听器B抛出异常而停止了侦听器A,则在您的设计中肯定存在错误

stop method on DefaultMessageListenerContainer did not worked but shutdown method worked perfectly. DefaultMessageListenerContainer上的stop方法无法正常工作,但shutdown方法可以正常工作。

 for(DefaultMessageListenerContainer defaultCont:containers){
         defaultCont.shutdown();
      }

Injecting a collection of DefaultMessageListenerContainer did not work for me, I use Spring Boot 1.4.x, with Spring 4.3.x 注入DefaultMessageListenerContainer的集合对我不起作用,我使用Spring Boot 1.4.x和Spring 4.3.x

Here's how I solved it: 这是我解决的方法:

package org.example.queue;

import org.springframework.jms.config.JmsListenerEndpointRegistry;
//import other stuffs

@Component
public class QueueManager {


   @Autowired
   JmsListenerEndpointRegistry endpointRegistry;


    public void shutdown() {
        endpointRegistry.getListenerContainers().forEach((container) -> {
            if (container.isRunning()) {
                log.debug("Shutting down listener: " + container.getClass().getName());
                container.stop();
            }
        });
    }

    public void start() {
        endpointRegistry.getListenerContainers().forEach((container) -> {
            if (!container.isRunning()) {
                log.debug("Starting listener: " + container.getClass().getName());
                container.start();
            }
        });
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM