将taskExecutor配置添加到带有IBM MQ JMS提供程序的SimpleMessageListenerContainer时,在每次onMessage执行后抛出以下异常: -
Execution of JMS message listener failed, and no ErrorHandler has been set.
com.ibm.msg.client.jms.DetailedIllegalStateException: JMSCC0033: A synchronous method call is not permitted when a session is being used asynchronously: 'getTransacted' The JMS specification does not permit the use of a session for synchronous methods when asynchronous message delivery is running. Create a separate session if you wish to use both synchronous methods and asynchronous delivery simultaneously.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:313)
at com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:388)
at com.ibm.msg.client.jms.internal.JmsErrorUtils.createException(JmsErrorUtils.java:104)
at com.ibm.msg.client.jms.internal.**JmsSessionImpl.checkSynchronousUsage**(JmsSessionImpl.java:2378)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.getTransacted(JmsSessionImpl.java:1525)
at com.ibm.mq.jms.MQSession.getTransacted(MQSession.java:801)
at org.springframework.jms.listener.**AbstractMessageListenerContainer.commitIfNecessary**(AbstractMessageListenerContainer.java:571)
at org.springframework.jms.listener.**AbstractMessageListenerContainer.doExecuteListener**(AbstractMessageListenerContainer.java:481)
at org.springframework.jms.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:439)
at org.springframework.jms.listener.SimpleMessageListenerContainer.processMessage(SimpleMessageListenerContainer.java:311)
at org.springframework.jms.listener.SimpleMessageListenerContainer$1$1.run(SimpleMessageListenerContainer.java:278)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
查看AbstractMessageListenerContainer.doExecuteListener方法,在调用侦听器之后,它将提交事务处理会话或确认是否为CLIENT_ACKNOWLEDGE。 根据JMS规范抛出异常 - http://docs.oracle.com/javaee/7/api/javax/jms/Session.html “一旦连接启动,任何具有一个或多个已注册消息侦听器的会话专用于向其传递消息的控制线程。客户端代码使用此会话或来自另一个线程的任何组成对象是错误的。此规则的唯一例外是使用会话或连接关闭方法。
当SMLC支持具有auto_acknowledge的taskExecutor时,为什么会发生这种情况? 我们使用的是Java 7,Spring 3.0.5,MQ 7.0.3。这是我们的配置: -
<task:annotation-driven executor="notifExecutor" />
<task:executor id="notifExecutor" pool-size="5-10" keep-alive="60" queue-capacity="10" rejection-policy="CALLER_RUNS"/>
<bean id="jmsOptInOutSMSContainer"
class="org.springframework.jms.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="mqWakeUpSMSFactory" />
<property name="destination" ref="optInOutSMSQueue" />
<property name="messageListener" ref="optInOptOutSMSListener" />
<property name="autoStartup" value="true" />
<property name="acceptMessagesWhileStopping" value="false" />
**<property name="taskExecutor" ref="notifExecutor" />**
<property name="concurrentConsumers" value="1" />
</bean>