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

升级spring-jms后setExceptionListener方法调用被禁止的问题排查

问题:Spring JMS升级后连接IBM MQ报错Method setExceptionListener not permitted

我使用@JmsListener消费部署在WAS上的IBM MQ消息,在spring-jms 5.2.22.RELEASE版本时:

  • 应用启动时会抛出如下异常:
DEBUG o.s.j.l.DefaultMessageListenerContainer Could not establish shared JMS Connection - leaving it up to asynchronous invokers to establish a Connection as soon as possible javax.jms.IllegalStateException: Method setExceptionListener not permitted
at com.ibm.ejs.jms.JMSCMUtils.methodNotPermittedException(JMSCMUtils.java:268)
at com.ibm.ejs.jms.JMSConnectionHandle.checkRestrictedMethod(JMSConnectionHandle.java:867)
at com.ibm.ejs.jms.JMSConnectionHandle.setExceptionListener(JMSConnectionHandle.java:361)
at org.springframework.jms.connection.SingleConnectionFactory.prepareConnection(SingleConnectionFactory.java:458)
at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:355)
at org.springframework.jms.connection.SingleConnectionFactory.getConnection(SingleConnectionFactory.java:328)
at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:243)
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:197)
[...]
  • 但后续连接能自动恢复,消息可以正常消费:
DEBUG o.s.j.l.DefaultMessageListenerContainer JMS message listener invoker needs to establish shared Connection
DEBUG o.s.j.l.DefaultMessageListenerContainer Successfully refreshed JMS Connection

将spring-jms升级到5.3.27后(实际从5.3.26版本开始出现问题),连接无法刷新,持续抛出如下异常,无法消费消息:

ERROR o.s.j.l.DefaultMessageListenerContainer Could not refresh JMS Connection for destination 'XXX' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: Method setExceptionListener not permitted
javax.jms.IllegalStateException: Method setExceptionListener not permitted
    at com.ibm.ejs.jms.JMSCMUtils.methodNotPermittedException(JMSCMUtils.java:268)
    at com.ibm.ejs.jms.JMSConnectionHandle.checkRestrictedMethod(JMSConnectionHandle.java:867)
    at com.ibm.ejs.jms.JMSConnectionHandle.setExceptionListener(JMSConnectionHandle.java:361)
    at org.springframework.jms.connection.SingleConnectionFactory.prepareConnection(SingleConnectionFactory.java:446)
    at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:355)
    at org.springframework.jms.connection.SingleConnectionFactory.getConnection(SingleConnectionFactory.java:328)
    at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:243)
    at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:197)
    [...]

相关代码

业务消费代码

@Transactional
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "XXX")
public void handleMessage(String message){ //... }

MQ配置类

@Configuration
@EnableTransactionManagement
@EnableJms
public class MqConfig{

@Bean
public ConnectionFactory mqConnectionFactory() throws NamingException{
   return (ConnectionFactory) new JndiObjectFactoryBean().getJndiTemplate().lookup("jms/MqConnFact"); 
}

@Bean
public CachingConnectionFactory cachingConnectionFactory() throws NamingException{
   CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
   cachingConnectionFactory.setTargetConnectionFactory(mqConnectionFactory());
   cachingConnectionFactory.setCacheConsumers(true);
   cachingConnectionFactory.setCacheProducers(true);
   cachingConnectionFactory.setSessionCacheSize(10);
   cachingConnectionFactory.setReconnectOnException(true);
   return cachingConnectionFactory;
}

@Bean
public JmsListenerContainerFactory jmsListenerContainerFactory() throws NamingException{
   DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
   containerFactory.setConnectionFactory(cachingConnectionFactory());
   containerFactory.setConcurrency("1");
   containerFactory.setSessionAcknowledgeMode(2);
   containerFactory.setTransactionManager(jmsTransactionManager());
   containerFactory.setCacheLevelName("CACHE_CONSUMER");
   containerFactory.setSessionTransacted(true);
   containerFactory.setReceiveTimeout(60000);
   return containerFactory;
}

我怀疑该问题与Spring Framework 5.3.26版本的某个变更相关,但不清楚具体解决办法,求排查思路。


排查思路

  • 绕过setExceptionListener调用:自定义SingleConnectionFactory子类,重写prepareConnection方法,跳过setExceptionListener的执行逻辑。因为Spring 5.3.26的变更可能强制在连接准备阶段设置该监听器,而WAS的MQ连接不允许此操作。
  • 调整CachingConnectionFactory配置:当前设置了setReconnectOnException(true),结合Spring的变更,可能在连接刷新时重复触发准备逻辑,导致每次都调用受限方法。可以尝试关闭该配置,或者调整缓存策略(比如临时关闭连接缓存作为验证)。
  • 使用原生ConnectionFactory:临时去掉CachingConnectionFactory包装,直接使用从JNDI获取的原生连接工厂,验证是否是缓存层导致的问题(注意这会失去缓存性能优势,仅作为排查手段)。
  • 检查WAS MQ连接工厂配置:登录WAS控制台,查看IBM MQ连接工厂是否有禁止调用setExceptionListener的限制,尝试调整配置解除限制,或者参考IBM官方文档确认该限制的原因。
  • 回退版本并跟进官方修复:如果业务紧急,暂时回退到5.3.25版本,同时关注Spring官方是否发布了兼容性修复版本,也可以向Spring社区提交该兼容性问题反馈。

内容的提问来源于stack exchange,提问作者adolzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:47:33