Spring JMS监听器即使在异常时也会确认

Bha*_*gav 5 java amazon-sqs amazon-web-services spring-jms spring-boot

我正在使用JMS向我的SQS队列发送/接收消息,但是即使在使用client_acknowledge时出现异常,我也无法重新发送消息.怎么做到这一点?我试过一个简单的测试,

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

}
Run Code Online (Sandbox Code Playgroud)

即使异常消息没有回到队列.

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

Gar*_*ell 5

您必须在DMLC中使用事务。

使用Session.AUTO_ACKNOWLEDGEsetSessionTransacted(true)

如果侦听器正常退出,则消息将被删除。如果侦听器引发异常,则消息将回滚到队列中。

您也可以将客户端模式用于事务,但是您必须自己确认成功的消息。

您不必使用带有的事务,SimpleMessageListenerContainer但仍必须引发异常以使消息重新排队。


Has*_*our 0

仅当侦听器停止并与代理断开连接时,消息才会返回队列,您所描述的行为位于 DefaultMessageListenerContainer 的客户端,它将消息分派到您的侦听器并管理异常和重试,代理不知道这些处理他只知道这些消息已发送给客户端并正在等待确认。MessageConsumer 的实现是否有重置或重新启动等方法取决于 SQS 的方法和功能。您可以尝试jms会话的recover()方法,但我认为这只会在客户端重新启动交付。 https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#recover--

这是一个不好的做法,但如果您重新启动连接或 DefaultMessageListenerContainer,未确认的消息将返回到代理并重新启动传递。