【问题标题】:spring jms global ErrorHandler not workingspring jms 全局 ErrorHandler 不起作用
【发布时间】:2018-04-18 17:24:36
【问题描述】:

MyProjectJmsListenerContainerFactory 类:

@Configuration
public class MyProjectJmsListenerContainerFactory {

    @Bean
    public JmsListenerContainerFactory<?> myFactory(
            ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer, 
            MyProjectJmsGlobalErrorHandler errorHandler) {
        ActiveMQConnectionFactory activeMQConnectionFactory =
                       (ActiveMQConnectionFactory)connectionFactory;
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setMaximumRedeliveries(1);
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

        DefaultJmsListenerContainerFactory factory = 
                 new DefaultJmsListenerContainerFactory();
        factory.setErrorHandler(errorHandler);
        configurer.configure(factory, activeMQConnectionFactory);
        return factory;
    }
}

MyProjectJmsGlobalErrorHandler 类:

@Component
public class MyProjectJmsGlobalErrorHandler implements ErrorHandler {

    @Override
    public void handleError(Throwable throwable) {
        System.out.println("JMS EXCEPTION HANDLER CAUGHT THE EXCEPTION !!");       
    }
}

JMSTextMessageConverter 类:

@Configuration
public class JMSTextMessageConverter {

    @Bean
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter mappingJackson2MessageConverter = 
                     new MappingJackson2MessageConverter();
        mappingJackson2MessageConverter.setTargetType(MessageType.TEXT);
        mappingJackson2MessageConverter.setTypeIdPropertyName("_type");

        return mappingJackson2MessageConverter;
    }   
}

JMSMessagePublisher 类:

@Component
public class JMSMessagePublisher {

    private JmsTemplate jmsTemplate;

    private MessageConverter messageConverter;

    @Autowired
    public JMSMessagePublisher(JmsTemplate jmsTemplate,    
                           MessageConverter messageConverter) {
        this.jmsTemplate = jmsTemplate;
        this.messageConverter = messageConverter;
    }

    public void publishMessage() {
        jmsTemplate.setMessageConverter(messageConverter);
        jmsTemplate.convertAndSend("test.q1", "Hello World");
    }
}

JMSListener 类:

@Component
public class JMSListener {

    @JmsListener(destination = "test.q1")
    public void subscribe(String message) throws Exception {
        System.out.println(" message received ::::::::"+message);
        throw new Exception("Exception from message listener ");
    }
}

我从上面的 subscribe 方法中抛出了一个异常,但无法通知到 ErrorHandler,我可以在日志中注意到以下警告。

WARN 1993 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : 
Execution of JMS message listener failed, and no ErrorHandler has been set.

我的 JMS 配置有什么问题,即如何设置 ErrorHandler 以便在 handleError(Throwable throwable) 方法中全局捕获/通知所有异常。

我使用JMSMessagePublisher 类中的publishMessage() 方法发布消息(如上所示)。

【问题讨论】:

    标签: java spring jms spring-jms


    【解决方案1】:

    ErrorHandler 仅用于处理侦听器在处理消息时抛出的错误(异常)。

    由于没有连接,所以还没有可以处理错误的消息。

    您可以编写自己的逻辑,不时尝试从连接工厂获取连接。

    编辑

    我刚刚进行了一个测试,它对我来说很好......

    @SpringBootApplication
    public class So49861714Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So49861714Application.class, args);
        }
    
        @Bean
        public ApplicationRunner runner(JmsTemplate template) {
            return args -> template.convertAndSend("foo", "testMessage");
        }
    
        @Bean
        public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
                DefaultJmsListenerContainerFactoryConfigurer configurer,
                ConnectionFactory connectionFactory,
                ErrorHandler myErrorHandler) {
            DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
            configurer.configure(factory, connectionFactory);
            factory.setErrorHandler(myErrorHandler);
            return factory;
        }
    
        @Bean
        public ErrorHandler myErrorHandler() {
            return t -> {
                System.out.println("In error handler");
                t.printStackTrace();
            };
        }
    
        @JmsListener(destination = "foo")
        public void listen(String in) {
            System.out.println(in);
            throw new RuntimeException("test");
        }
    
    }
    

    testMessage
    In error handler
    org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.example.So49861714Application.listen(java.lang.String)' threw exception; nested exception is java.lang.RuntimeException: test
    ...
    Caused by: java.lang.RuntimeException: test
    

    我刚刚注意到您的工厂 bean 被称为 myFactory,但您没有在 @JmsListener 中指定它。 如果您的应用程序是 Spring Boot 应用程序,我猜监听器正在使用 Boot 的 jmsListenerContainerFactory bean(这是默认 bean 名称)。

    【讨论】:

    • +1,谢谢你的回答,我明白你的意思了,用日志更新了上面的问题,也就是说,这次即使我的监听器抛出异常,它也没有被通知到ErrorHandler,你能帮忙吗?
    猜你喜欢
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 2014-08-24
    • 2021-12-15
    • 1970-01-01
    • 2017-03-31
    相关资源
    最近更新 更多