user705414
user705414

Reputation: 21200

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

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?

Upvotes: 31

Views: 68902

Answers (5)

Sivaram Rasathurai
Sivaram Rasathurai

Reputation: 6333

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.

Upvotes: 0

BuckBazooka
BuckBazooka

Reputation: 921

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

Upvotes: 8

Tsolak Barseghyan
Tsolak Barseghyan

Reputation: 1064

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

Upvotes: 1

Kuchi
Kuchi

Reputation: 4674

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

Upvotes: 6

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

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?

Upvotes: 23

Related Questions