简体   繁体   English

Spring JMS侦听器即使在发生异常时也进行确认

[英]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. 我正在使用JMS将消息发送/接收到我的SQS队列,但是即使在使用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. 您必须在DMLC中使用事务。

Use Session.AUTO_ACKNOWLEDGE and setSessionTransacted(true) . 使用Session.AUTO_ACKNOWLEDGEsetSessionTransacted(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. 您不必将事务与SimpleMessageListenerContainer一起使用,但仍必须引发异常以使消息重新排队。

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. 仅当侦听器停止并且与代理断开连接时,消息才返回队列,您描述的行为是在DefaultMessageListenerContainer的客户端上,该消息将消息分发给侦听器并管理异常和重试,代理不知道这些处理方式并且他只知道这些消息已分发给客户端,并且正在等待确认。 It is depends on the SQS methods and capabilities if there a method like reset or restart on the implementation of MessageConsumer. 如果在MessageConsumer的实现中是否存在诸如reset或restart这样的方法,则取决于SQS方法和功能。 You can try recover() method of jms session but i think this will only restart delivery on the client side. 您可以尝试jms会话的restore()方法,但我认为这只会在客户端重新启动传递。 https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#recover-- 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. 这不是一个好习惯,但是如果您重新启动连接或DefaultMessageListenerContainer,则未确认的消息将返回给代理,并重新开始传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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