【问题标题】:Closing Session when using Spring's CachingConnectionFactory使用 Spring 的 CachingConnectionFactory 时关闭会话
【发布时间】:2013-09-22 16:06:39
【问题描述】:

Spring CachingConnectionFactory相关的java文档here有注释:

注意:此 ConnectionFactory 需要显式关闭从其共享连接中获得的所有会话。无论如何,这是本机 JMS 访问代码的通常建议。但是,对于这个 ConnectionFactory,它的使用是强制性的,以便实际允许 Session 重用。

我不清楚如何在我的应用程序中使用以下给定配置来处理这个问题。

<bean id="springApp" class="com.codereq.springcore.jms.SpringJMSListenerApp"  />

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="destination" ref="destination"/>
    <property name="messageListener" ref="messageListener"/>
    <property name="sessionTransacted" value="true"/>
    <property name="concurrentConsumers" value="5" />
    <property name="maxConcurrentConsumers" value="15" />
</bean>

<bean id="messageListener" class="com.codereq.springcore.jms.MessageListenerApp" />

<bean id="jmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"
        p:targetConnectionFactory-ref="emsConnectionFactory"
        p:sessionCacheSize="100" 
        p:cacheConsumers="true" />

<bean id="emsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="GenericConnectionFactory"/>
    <property name="jndiTemplate" ref="jndiTemplate"/>
</bean>


<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">com.tibco.tibjms.naming.TibjmsInitialContextFactory</prop>
            <prop key="java.naming.provider.url">tibjmsnaming://localhost:7222</prop>
            <prop key="java.naming.security.principal">admin</prop>
            <prop key="java.naming.security.credentials">admin</prop>
        </props>
    </property>
</bean>

<bean id="destination" class="com.tibco.tibjms.TibjmsQueue">
    <constructor-arg value="com.sample.queue" />
</bean>

监听器类是这样的:

public class MessageListenerApp implements MessageListener {

private static int c = 0;

@Override
public void onMessage(Message arg0) {

    try {
        System.out.println("Received Message..."+arg0.getStringProperty("MessageNum")+". Waiting to finish..");
        Thread.sleep(2000);
        System.out.println("Finished processing.."+arg0.getStringProperty("MessageNum")+".."+(c++));
    } catch (Exception e) {
        e.printStackTrace();
    }

}

}

我如何遵循从共享连接获得的会话应该明确关闭的建议?

遇到 SessionAwareMessageListener 接口,该接口提供了提供 Session 句柄的 onMessage 方法。那么要正确实现会话关闭,是否应该实现这个接口呢?

【问题讨论】:

    标签: java spring jms spring-jms


    【解决方案1】:

    将缓存连接工厂与侦听器容器一起使用通常不是一个好主意,尤其是在使用 maxConcurrentConsumers > concurrentConsumers 时 - 您最终会在缓存中缓存消费者,它们会在没有消息的地方获取消息监听器,这样的消息可能会“卡住”。

    所以,在这种情况下不要使用CCF,它实际上是为生产者而设计的。

    由于容器管理并发,会话/消费者是长期存在的,不需要缓存。

    【讨论】:

    • 但这个问题似乎仍然没有答案。让消息生产者缓存在另一个场景中。如何处理从 CCF 获得的会话的显式关闭?
    • session.close() - javadoc 注释只是说会话仅在客户端关闭时返回到池中。如果您需要物理关闭,请不要使用CachingConnectionFactory。 Spring 客户端(JmsTemplate、监听器容器)会在适当的时候关闭连接。
    • 我已经为 JMSTemplate 配置了一个 CachingConnectionFactory 以与 Tibco EMS 一起使用。我的消息生产者在 tomcat 服务器中运行。即使tomcat正常关闭后,EMS中的连接仍然没有被破坏。有没有办法关闭它?
    • 连接工厂实现了DisposableBean,这意味着当应用上下文被销毁时,它的destroy()方法将被调用(关闭连接)。如果它是一个普通的 Web 应用程序上下文,那应该会自动发生;如果您自己管理上下文的生命周期,则由您来销毁它。
    • 它是一个普通的 Web 应用程序上下文。上下文的生命周期仅由 Spring 管理。在博客Using Spring to Send JMS messages 中,我可以看到将daemon=true 选项添加到传输将终止连接。但在我的情况下它并没有醒来。
    【解决方案2】:

    应用程序在使用DefaultMessageListenerContainer 时不需要关闭会话,它会创建所需的会话并在关闭期间关闭它们。

    根据我的理解,当应用程序使用 CachingConnectionFactory 参考创建 Session 时,您提到的注释适用于关于哪个 spring 将不知道的任何线索。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-26
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-27
      • 2010-12-06
      • 2014-05-05
      相关资源
      最近更新 更多