简体   繁体   中英

Spring JMS listener acknowledging even when exception

I am using JMS to send/receive messages to my SQS queue, however i am unable to redeliver the message when there is an exception even while using client_acknowledge. How to achieve this? I tried a simple test,

@JmsListener(destination = "test-normalqueue")
public void receiveNormalQueue(String message)
{

    try {
        logger.info("message received in normal queue: " + message);
        throw new NullPointerException();

    } catch (Exception e) {

        logger.error(LoggingUtil.getStackTrace(e));;
    }

}

Even after exception message doesnt come back to queue.

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(getSQSConnectionFactory());
    factory.setConcurrency("1-2");
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}

You have to use transactions with the DMLC.

Use Session.AUTO_ACKNOWLEDGE and setSessionTransacted(true) .

If the listener exits normally, the message is removed. If the listener throws an exception, the message will be rolled-back onto the queue.

You can also use client mode with transactions, but you have to acknowledge successful messages yourself.

You don't have to use transactions with a SimpleMessageListenerContainer but you still have to throw an exception to get the message requeued.

The Messages comes back to queue only if the listener stops and disconnects from the broker, the behavior you are describing is on the client side on the DefaultMessageListenerContainer which dispatch messages to your listener and manage exceptions and retries, the broker is not aware of those treatments and he only knows that these messages are dispatched to the client and is waiting acknowledgements. It is depends on the SQS methods and capabilities if there a method like reset or restart on the implementation of MessageConsumer. You can try recover() method of jms session but i think this will only restart delivery on the client side. https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#recover--

This is a not good practice but if you restart the connection or the DefaultMessageListenerContainer the messages not acknowledged comes back to broker and the delivery restarts.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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