【问题标题】:Execution of JMS message listener failed, and no ErrorHandler has been setJMS消息监听执行失败,没有设置ErrorHandler
【发布时间】:2012-02-13 21:42:01
【问题描述】:

当我使用 Spring 收听 JMS 消息时,我收到了上述错误。

我想知道如何将 Errorhandler 添加到 JMS 侦听器中?

【问题讨论】:

    标签: java spring jms spring-jms


    【解决方案1】:

    AbstractMessageListenerContainer上有一个属性:

    <bean id="listener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="errorHandler" ref="someHandler"/>
        <property name="destinationName" value="someQueue"/>
        <property name="connectionFactory" ref="connectionFactory"/>
    </bean>
    

    其中someHandler 是实现ErrorHandler 的bean:

    @Service
    public class SomeHandler implements ErrorHandler {
    
        @Override
        public void handleError(Throwable t) {
            log.error("Error in listener", t);
        }
    }
    

    但请注意,根据documentation

    此消息侦听器的默认行为 [...] 将在错误级别记录任何此类异常。 [...] 但是,如果需要错误处理,则可以将 ErrorHandler 策略的任何实现提供给 setErrorHandler(ErrorHandler) 方法。

    看看你的日志,也许异常已经被记录了?

    【讨论】:

    • 看起来异常是默认使用 WARN 级别记录的。
    • @user705414:这似乎是文档中的一个错误:AbstractMessageListenerContainer.invokeErrorHandler() 确实使用了log.warn()。我使用@Service 来自动检测 bean,当然任何声明错误处理程序 bean 的方式都可以。
    【解决方案2】:

    我喜欢它又短又甜!

        @Bean
    JmsListenerContainerFactory<?> jmsContainerFactory(ConnectionFactory connectionFactory) {
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setErrorHandler(t -> {
             log.error("Error in listener!", t);
           });
        return factory;
    }
    

    【讨论】:

      【解决方案3】:

      没有xml配置。我在 ApplicationContext 中做了以下操作。

      @Bean
      JmsListenerContainerFactory<?> jmsContainerFactory(ConnectionFactory connectionFactory,
              SomeHandler errorHandler) {
          SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
          factory.setConnectionFactory(connectionFactory);
          factory.setErrorHandler(errorHandler);
          return factory;
      }
      
      
      // From Tomasz answer
      @Service
      public class SomeHandler implements ErrorHandler {
      
          @Override
          public void handleError(Throwable t) {
              log.error("Error in listener", t);
          }
      }
      

      【讨论】:

        【解决方案4】:

        如果使用默认工厂:

            @Bean
            public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory,
                    SomeHandler errorHandler) {
                DefaultJmsListenerContainerFactory factory =
                        new DefaultJmsListenerContainerFactory();
                factory.setConnectionFactory(connectionFactory);
                factory.setErrorHandler(errorHandler);
                return factory;
            }
        

        【讨论】:

          【解决方案5】:

          我检查了答案,但没有人告诉我们这个错误处理程序是什么以及为什么我们需要设置这个错误处理程序? JMSException 不需要此 errorHandler。 JMSException 需要被 exceptionListener 监听,如下所示

          DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
                  factory.setExceptionListener(new ExceptionListener() {
                      @Override
                      public void onException(JMSException exception) {
                          System.out.println("JMSException is occurred " + exception);
                          //TODO the way you need to handle the exception
                      }
                  });
          
          

          这个 ErrorHandler 用于在处理消息时抛出任何未捕获的异常时调用。

          默认情况下,不会有 ErrorHandler,因此错误级别的日志记录是唯一的结果。

           DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
                  factory.setErrorHandler(new ErrorHandler() {
                      @Override
                      public void handleError(Throwable t) {
                          System.out.println("Unknown Exception is occurred " + t);
                      }
                  });
          

          这是最好的方法吗?

          设置errorHandler是一种处理消息处理过程中发生的未知异常的方法。但是当我们看这个场景时,我们错过了 JMS 的实际消息。对于故障排除,消息将起到至关重要的作用。所以我的方法如下 在 JMSListener 方法中

           @JmsListener(destination = "${ibm.mq.queue.response.edmonton}", containerFactory = "mqContainerFactory", concurrency = "${ibm.mq.concurrency}")
              public void receiveMessage(Message message) {
               try{
                  //MessageProcessingCode
               }catch(Exception ex){
                 //Define a custom ErrorHandler which can take exception and message
                 CustomErrorHandler eh = new CustomErrorHandler();
                 eh.handleError(ex,message);
               }
              }
          

          请注意,我们不会捕获 throwable,因为 Throwable 是 Java 中所有错误和异常的超类。错误是所有错误的超类,这些错误并不意味着被应用程序捕获。捕获 Throwable 或 Error 也会捕获 OutOfMemoryError 和 InternalError,应用程序不应尝试从中恢复。

          【讨论】:

          • receiveMessage 函数中的 try catch 块没有捕捉到 JMS Listener 中抛出的异常
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-29
          • 2017-03-15
          • 1970-01-01
          • 2014-02-20
          • 2013-12-16
          • 2020-07-18
          • 1970-01-01
          相关资源
          最近更新 更多