Execution of JMS message listener failed, and no ErrorHandler has been set
Asked Answered
B

5

31

When I use Spring to listen to JMS messages, I receievd the above error.

I am wondering how to add an Errorhandler into the JMS listener?

Botch answered 19/1, 2012 at 7:38 Comment(0)
U
23

There is a property on 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>

Where someHandler is a bean implementing ErrorHandler:

@Service
public class SomeHandler implements ErrorHandler {

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

However note that according to the documentation:

The default behavior of this message listener [...] will log any such exception at the error level. [...] However, if error handling is necessary, then any implementation of the ErrorHandler strategy may be provided to the setErrorHandler(ErrorHandler) method.

Check out your logs, maybe the exception is already logged?

Ulcerate answered 19/1, 2012 at 7:50 Comment(3)
Looks like the exception is logged using WARN level by default.Botch
@user705414: this seems to be a mistake in the documentation: AbstractMessageListenerContainer.invokeErrorHandler() indeed uses log.warn(). I use @Service to autodetect the bean, of course any way to declare the error handler bean is fine.Ulcerate
Filed a Github issue regarding WARN level github.com/spring-projects/spring-framework/issues/30730Unruly
H
8

I like it short and sweet!

    @Bean
JmsListenerContainerFactory<?> jmsContainerFactory(ConnectionFactory connectionFactory) {
    SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setErrorHandler(t -> {
         log.error("Error in listener!", t);
       });
    return factory;
}
Horvath answered 30/11, 2017 at 8:35 Comment(0)
Q
6

Without the xml configuration. I did the following in the 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);
    }
}
Quadriga answered 8/4, 2016 at 13:9 Comment(0)
T
1

In case when default factory used:

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory,
            SomeHandler errorHandler) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setErrorHandler(errorHandler);
        return factory;
    }
Tolley answered 8/12, 2016 at 11:18 Comment(0)
S
0

I checked the answers but No one tells about what is this error handler and why we need to set this error handler? This errorHandler is not needed for the JMSException. JMSException needs to be listened by exceptionListener as like below

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
            }
        });

This ErrorHandler is used to be invoked in case of any uncaught exceptions thrown while processing a message.

By default, there will be no ErrorHandler so that error-level logging is the only result.

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

Is this Best Approach?

Setting up an errorHandler is a way to handle the unknown exceptions that are occurred during the message processing. but when we look at this scenario, we miss the actual message of JMS. For troubleshooting, the message will play a vital role. So My approach like below In JMSListener Method

 @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);
     }
    }

Please note that we will not catch the throwable because Throwable is the superclass of all errors and exceptions in Java. Error is the superclass of all errors, which are not meant to be caught by applications. Catching either Throwable or Error will also catch OutOfMemoryError and InternalError, from which an application should not attempt to recover.

Shoulders answered 22/10, 2021 at 16:17 Comment(1)
The try catch block in the receiveMessage function doesn't catch the exception thrown in the JMS ListenerIdiot

© 2022 - 2024 — McMap. All rights reserved.