我有一个使用Spring连接到TIBCO(队列)的独立应用程序。有时,由于各种原因,服务器会关闭TIBCO连接。大多数事情正在从此恢复。但是,由于下面的错误,有时JmsTemplate无法发送响应。我有一个重试,但同样的错误不断发生(见下面的跟踪)。
可能很重要的细节:
我正在使用DefaultMessageListenerContainer来获取请求并在该接收线程中发送响应。另外,我对DefaultMessageListenerContainer和JmsTemplate都使用相同的连接工厂。
Caused by: org.springframework.jms.IllegalStateException: Session is closed; nested exception is javax.jms.IllegalStateException: Session is closed
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:279)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:487)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:559)
at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:682)
at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:670)
at org.springframework.integration.jms.JmsSendingMessageHandler.send(JmsSendingMessageHandler.java:149)
at org.springframework.integration.jms.JmsSendingMessageHandler.handleMessageInternal(JmsSendingMessageHandler.java:116)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
... 83 more
Caused by: javax.jms.IllegalStateException: Session is closed
at com.tibco.tibjms.TibjmsxSessionImp._createProducer(TibjmsxSessionImp.java:1067)
at com.tibco.tibjms.TibjmsxSessionImp.createProducer(TibjmsxSessionImp.java:5080)
at org.springframework.jms.core.JmsTemplate.doCreateProducer(JmsTemplate.java:1114)
at org.springframework.jms.core.JmsTemplate.createProducer(JmsTemplate.java:1095)
at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:591)
at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:562)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484)
... 89 more
使用Spring框架与TIBCO队列进行通信。这是配置。 DefaultMessageListenerContainer接收消息并进行处理,并使用JmsTemplate发回响应。连接工厂在接收方和发送方之间共享(这可能是个问题吗?)。
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<constructor-arg ref="tibcoJNDI" />
<property name="targetConnectionFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="tibcoJNDI"/>
<property name="jndiName" value="${tibco.queueConnectionFactory}" />
</bean>
</property>
<property name="reconnectOnException" value="true"/>
</bean>
<bean id="client.req.msg.lstnr" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="autoStartup" value="false"/>
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="ext_client.request.queue"/>
<property name="sessionAcknowledgeMode" value="3"/>
<property name="concurrentConsumers" value="6"/>
<property name="receiveTimeout" value="60000"/>
</bean>
<jms:outbound-channel-adapter
jms-template="ext.outbound.jms.template"
channel="jms.to.ext.clnt.reply"/>
<bean id="ext.outbound.jms.template" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="ext_client.reply.queue"/>
<property name="timeToLive" value="10800000" />
<property name="explicitQosEnabled" value="true" />
</bean>
可能有用的另一个细节。我只是注意到第一个例外实际上是不同的。有一个&#34;连接已关闭&#34;异常首先跟随多个&#34;会话已关闭&#34;异常(重试时)。
Caused by: javax.jms.JMSException: Connection is closed
at com.tibco.tibjms.TibjmsxLink.sendRequest(TibjmsxLink.java:322)
at com.tibco.tibjms.TibjmsxLink.sendRequest(TibjmsxLink.java:286)
at com.tibco.tibjms.TibjmsxLink.sendRequestMsg(TibjmsxLink.java:261)
at com.tibco.tibjms.TibjmsxSessionImp._createProducer(TibjmsxSessionImp.java:1075)
at com.tibco.tibjms.TibjmsxSessionImp.createProducer(TibjmsxSessionImp.java:5080)
at org.springframework.jms.core.JmsTemplate.doCreateProducer(JmsTemplate.java:1114)
at org.springframework.jms.core.JmsTemplate.createProducer(JmsTemplate.java:1095)
at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:591)
at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:562)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484)
... 89 more
答案 0 :(得分:1)
在这种情况下,Spring似乎无法正确处理。我通过重写JmsTemplate(下面的代码)并自己处理异常(清理会话和连接)解决了此问题。我希望这会有所帮助。
public <T> T execute(SessionCallback<T> action, boolean startConnection) throws JmsException {
try {
return super.execute(action, startConnection);
} catch (JmsException jmse) {
logger.error("Exception while executing in JmsTemplate (will cleanup session & connection): ", jmse);
Object resourceHolder =
TransactionSynchronizationManager.getResource(getConnectionFactory());
if (resourceHolder != null && resourceHolder instanceof JmsResourceHolder) {
((JmsResourceHolder)resourceHolder).closeAll();
}
throw jmse;
}
}
答案 1 :(得分:0)
这个答案可能会有所帮助https://stackoverflow.com/a/24494739/208934特别是:
使用JMS时,您不应该真正缓存JMS会话(和 任何悬挂的东西,如制片人)。原因是 JMS会话是JMS中的工作单元,因此应该是 短命的物体。在Java EE世界中,JMS会话也可能 以全球交易为例,所以需要 范围正确。
听起来你正在重复使用同一个会话进行多项操作。
我在一些测试中看到过这个问题,并告诉Spring使用连接池通常会修复它。如果您使用的是active-mq,则可以使用属性spring.activemq.pooled=true
完成。我不是100%Tibco如何完成同样的事情。
通过定义将覆盖默认值的PooledConnectionFactory
bean,您可能会获得相同的结果。