You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot @JmsListener设CLIENT_ACKNOWLEDGE未调用ack仍消费消息

问题:Spring Boot中@JmsListener配置CLIENT_ACKNOWLEDGE但未调用acknowledge()消息仍被消费

在Spring Boot项目中使用@JmsListener消费消息,已将Session设置为CLIENT_ACKNOWLEDGE,同时在application.properties配置了spring.jms.listener.acknowledge-mode=CLIENT,但未调用msg.acknowledge()方法时,消息依然被消费掉。


相关配置代码

MQ配置类

import javax.jms.ConnectionFactory;
import javax.jms.Session;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

@EnableJms
@Configuration
public class MQConfiguration {
    protected final Log logger = LogFactory.getLog(getClass());

    @Bean(name = "jmsListenerContainerFactory")
    DefaultJmsListenerContainerFactory jmsContainerFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {

        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setErrorHandler(t -> {
            logger.warn("An error has occurred in the transaction");
            logger.error(t.getCause().getMessage());
        });
        factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        configurer.configure(factory, connectionFactory);
        factory.setConcurrency("1");
        factory.setSessionTransacted(false);
        
        return factory;
    }    
}

消息消费方法

@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "school.XXXX.request.clock-in", concurrency = "1")
public void consumeMessageFromMQ(String message, Message msg) throws Throwable {
    // 业务逻辑,未调用msg.acknowledge()
} 

依赖版本信息

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.7.15</version>
   <relativePath />
</parent>
<properties>
   <java.version>17</java.version>
</properties>
<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>artemis-jms-client</artifactId>
</dependency>    
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-artemis</artifactId>
</dependency>

原因分析及解决办法

核心原因

  1. 配置顺序错误:你先设置了Session.CLIENT_ACKNOWLEDGE,再调用configurer.configure(factory, connectionFactory),而DefaultJmsListenerContainerFactoryConfigurer会根据Spring Boot的自动配置参数覆盖你手动设置的会话确认模式。
  2. Spring JMS容器默认行为:即便是配置了CLIENT_ACKNOWLEDGE,DefaultJmsListenerContainerFactory默认会在消息消费方法正常执行完成后自动确认消息,无需手动调用acknowledge()。

解决办法

1. 调整配置顺序,确保自定义配置生效

把configurer.configure的调用放在自定义配置之前,让手动设置覆盖自动配置:

@Bean(name = "jmsListenerContainerFactory")
DefaultJmsListenerContainerFactory jmsContainerFactory(ConnectionFactory connectionFactory,
        DefaultJmsListenerContainerFactoryConfigurer configurer) {

    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // 先应用自动配置
    configurer.configure(factory, connectionFactory);
    
    factory.setErrorHandler(t -> {
        logger.warn("An error has occurred in the transaction");
        logger.error(t.getCause().getMessage());
    });
    // 再设置自定义参数,覆盖自动配置
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    factory.setConcurrency("1");
    factory.setSessionTransacted(false);
    
    return factory;
}    

2. 禁用容器自动确认,完全手动控制

如果需要必须手动调用acknowledge()才确认消息,需添加setAcknowledgeOnException(false)配置:

factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setSessionTransacted(false);
// 禁用异常时的自动确认,且正常执行后也不自动确认
factory.setAcknowledgeOnException(false);

配置后,只有手动调用msg.acknowledge()时消息才会被确认;方法抛出异常时,消息不会自动确认,会退回队列。

3. 检查Artemis Broker配置

确认Artemis Broker的consumer-window-size等参数没有设置为自动确认消息的模式,避免Broker主动确认未被客户端处理的消息。


内容的提问来源于stack exchange,提问作者Mowrya K B P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:57:18