JMS Template确认前关闭连接致会话异常问题排查
问题:JMS消费者确认消息时抛出Session已关闭异常
消费者通过Spring JmsTemplate读取MQ消息后,执行acknowledge()时抛出如下异常:
com.ibm.msg.client.jms.DetailedIllegalStateException: JMSCC0020: This session is closed. An application called a method that must not be used after the session is closed. Ensure that the session is not closed before calling the method.
相关配置与代码
Spring Bean配置
<beans> <bean id="mqDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"> </bean> <bean id="QUEUE_CONNECTION_FACTORY" class="com.ibm.mq.jms.MQConnectionFactory" > <property name="transportType" value="1" /> <property name="queueManager" value="QM.XXX" /> <property name="hostName" value="XXX.com" /> <property name="port" value="XXX" /> <property name="channel" value="XXX" /> <property name="SSLCipherSuite" value="XXX" /> </bean> <bean id="destination" class="com.ibm.mq.jms.MQQueue"> <constructor-arg value="INTERQUEUE" /> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="QUEUE_CONNECTION_FACTORY" /> <property name="destinationResolver" ref="mqDestinationResolver"/> <property name="defaultDestination"> <ref bean="destination" /> </property> <property name="pubSubDomain" value="false"/> <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/> </bean> <bean id="messageConsumer" class="com.jms.JmsMessageConsumer"> <property name="jmsTemplate" ref="jmsTemplate"/> </bean> </beans>
消费者类代码
import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; import org.springframework.jms.core.JmsTemplate; public class JmsMessageConsumer { private JmsTemplate jmsTemplate; public JmsTemplate getJmsTemplate() { return jmsTemplate; } public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public Message receiveMessage() throws JMSException { System.out.println("Start : Inside JMS message Consumer"); Message msg =(Message)getJmsTemplate().receive(); msg.acknowledge(); System.out.println("End : Inside JMS message Consumer"); return msg; }}
原因分析
- JmsTemplate的
receive()方法默认会自动创建Session/Connection,完成操作后立即关闭。当你在receive()之后调用msg.acknowledge()时,该消息所属的Session已经被JmsTemplate销毁,因此触发"Session已关闭"的异常。 - 虽然配置了
CLIENT_ACKNOWLEDGE手动确认模式,但JmsTemplate的默认生命周期管理逻辑导致Session无法在receive()之后保留。
解决方案
方案1:使用JmsTemplate回调方法在Session生命周期内完成确认
通过execute()方法将消息接收和确认逻辑放在同一个Session上下文里,避免Session提前关闭:
public Message receiveMessage() throws JMSException { System.out.println("Start : Inside JMS message Consumer"); return getJmsTemplate().execute(session -> { // 在当前session内创建消费者 javax.jms.MessageConsumer consumer = session.createConsumer(getJmsTemplate().getDefaultDestination()); Message msg = consumer.receive(); if (msg != null) { // 此时session仍处于活跃状态,可安全确认 msg.acknowledge(); } System.out.println("End : Inside JMS message Consumer"); return msg; }, true); // 让JmsTemplate负责关闭Connection }
方案2:配置JmsTemplate缓存Session
修改JmsTemplate的缓存级别,让它复用Session而非每次操作都关闭:
在Spring配置的jmsTemplate中添加属性:
<property name="cacheLevelName" value="CACHE_SESSION"/>
注意:缓存的Session并非线程安全,多线程消费场景下需谨慎使用。
方案3:改用消息监听器模式(推荐)
实现MessageListener接口,由Spring统一管理Session生命周期,在onMessage方法内安全执行确认:
- 修改消费者类:
import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; public class JmsMessageConsumer implements MessageListener { @Override public void onMessage(Message msg) { System.out.println("Start : Inside JMS message Consumer"); try { msg.acknowledge(); System.out.println("End : Inside JMS message Consumer"); } catch (JMSException e) { // 按需处理异常 e.printStackTrace(); } } }
- 添加消息监听容器配置:
<bean id="jmsListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="QUEUE_CONNECTION_FACTORY"/> <property name="destination" ref="destination"/> <property name="messageListener" ref="messageConsumer"/> <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/> </bean>
这种方式是Spring JMS消费的标准实现,能有效避免Session生命周期管理问题。
内容的提问来源于stack exchange,提问作者Sarvesh H
相关产品推荐
相关产品推荐

