Should I or shouldn't I use the CachingConnect

2019-07-20 18:39发布

Based on long standing information about using the JMSTemplate with hornetq we have been using the CachingConnectionFactory when connecting to the server. Here is an example configuration, very similar to one that we are using:

<bean id="jmsConnectionFactory" class="org.hornetq.jms.client.HornetQJMSConnectionFactory">
    <constructor-arg name="ha">
        <value>false</value>
    </constructor-arg>
    <constructor-arg name="initialConnectors">
        <bean class="org.hornetq.api.core.TransportConfiguration">
            <constructor-arg value="org.hornetq.core.remoting.impl.netty.NettyConnectorFactory" />
            <constructor-arg>
                <map key-type="java.lang.String" value-type="java.lang.Object">
                    <entry>
                        <key>
                            <util:constant static-field="org.hornetq.core.remoting.impl.netty.TransportConstants.HOST_PROP_NAME"/>
                        </key>
                        <value>${message-server.host}</value>
                    </entry>
                    <entry>
                        <key>
                            <util:constant static-field="org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME"/>
                        </key>
                        <value>${message-server.port}</value>
                    </entry>
                </map>
            </constructor-arg>
        </bean>
    </constructor-arg>
</bean>

<bean id="connectionFactory"
    class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
    <property name="targetConnectionFactory" ref="jmsConnectionFactory" />
    <property name="username" value="${message-server.user-name}" />
    <property name="password" value="${message-server.password}" />
</bean>

<bean id="caching.connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="connectionFactory" />
    <property name="sessionCacheSize" value="${session-cache}" />
    <property name="cacheProducers" value="${cache-producers}" />
    <property name="cacheConsumers" value="${cache-consumers}" />
</bean>

<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="connectionFactory" />
</bean>

<!-- Input Integration -->

<bean id="inputTopic" class="org.hornetq.jms.client.HornetQTopic">
    <constructor-arg>
        <value>${topicName}</value>
    </constructor-arg> 
</bean>
<int-jms:message-driven-channel-adapter connection-factory="connectionFactory"
    destination="inputTopic" 
    transaction-manager="transactionManager"
    pub-sub-domain="true" 
    channel="command.serialized.objectInputChannel" />

This has worked for us for almost 3 years now. When attempting to upgrade to the latest hornetq libraries we are getting exceptions similar to this:

2014-05-22 08:56:59,063 [Service-0] ERROR Error sending event to channel allOutput.channel 
org.springframework.integration.MessageHandlingException: error occurred in message handler [org.springframework.integration.jms.JmsSendingMessageHandler#0]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:79) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:178) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:149) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:330) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:169) ~[spring-integration-core-3.0.2.RELEASE.jar:na]

    ... lines omitted to fit

    at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:169) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:134) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:178) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:149) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    at c.i.e.p.ListenerChannelAdapter.sendEventToChannel(ListenerChannelAdapter.java:147) [processing-library-1.6.0-SNAPSHOT.jar:na]
    at c.i.e.p.ListenerChannelAdapter.update(ListenerChannelAdapter.java:75) [processing-library-1.6.0-SNAPSHOT.jar:na]
    at com.espertech.esper.core.service.EPRuntimeImpl.processMatches(EPRuntimeImpl.java:924) [esper-4.9.0.jar:na]
    at com.espertech.esper.core.service.EPRuntimeImpl.processWrappedEvent(EPRuntimeImpl.java:459) [esper-4.9.0.jar:na]
    at com.espertech.esper.core.thread.InboundUnitSendMap.run(InboundUnitSendMap.java:54) [esper-4.9.0.jar:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_55]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_55]
    at java.lang.Thread.run(Unknown Source) [na:1.7.0_55]
Caused by: org.springframework.jms.IllegalStateException: Producer is closed; nested exception is javax.jms.IllegalStateException: Producer is closed
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:279) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:494) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:566) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:689) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.integration.jms.JmsSendingMessageHandler.send(JmsSendingMessageHandler.java:139) ~[spring-integration-jms-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.jms.JmsSendingMessageHandler.handleMessageInternal(JmsSendingMessageHandler.java:112) ~[spring-integration-jms-3.0.2.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73) ~[spring-integration-core-3.0.2.RELEASE.jar:na]
    ... 140 common frames omitted
Caused by: javax.jms.IllegalStateException: Producer is closed
    at org.hornetq.jms.client.HornetQMessageProducer.checkClosed(HornetQMessageProducer.java:520) ~[hornetq-jms-client-2.4.1.Final.jar:na]
    at org.hornetq.jms.client.HornetQMessageProducer.getDeliveryMode(HornetQMessageProducer.java:127) ~[hornetq-jms-client-2.4.1.Final.jar:na]
    at org.springframework.jms.connection.CachedMessageProducer.<init>(CachedMessageProducer.java:89) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.getCachedProducer(CachingConnectionFactory.java:388) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.invoke(CachingConnectionFactory.java:331) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at com.sun.proxy.$Proxy16.createProducer(Unknown Source) ~[na:na]
    at org.springframework.jms.core.JmsTemplate.doCreateProducer(JmsTemplate.java:1044) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.createProducer(JmsTemplate.java:1025) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:598) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:569) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:491) ~[spring-jms-4.0.4.RELEASE.jar:4.0.4.RELEASE]
    ... 145 common frames omitted

Upon investigation it seems to be related to usage of caching, but there doesn't seem to be any clear answer as to whether or not we should cache.

The folks at hornetq/jboss seem to indicate that it is an anti-pattern to not use caching as indicated in several articles I have read over the years here is one such article:

https://community.jboss.org/wiki/CanIUseTheSpringJMSTemplateWithHornetQ

But there seem to be conflicting opinions by some of the guys from spring.

I have seen a few notes from Gary Russell on the topic (https://stackoverflow.com/users/1240763/gary-russell)

several posts indicate not to use CachingConnectionFactory with the DefaultMessageListenerContainer.

When is it appropriate to cacheConsumers when using Spring CachingConnectionFactory?

Closing Session when using Spring's CachingConnectionFactory

We went through and removed the CachingConnectionFactory from all of our int-jms:message-driven-channel-adapter 's and were still seeing the above exceptions it was not until I turned off the caching of the consumers and the producers that it went away.

Can someone give me a pointer as to how the caching should work, and if we have it set up correctly is this a bug in the new hornetq server?

1条回答
家丑人穷心不美
2楼-- · 2019-07-20 19:31

Which version of spring are you using? I believe this is actually caused by a bug in spring that causes it not to work correctly with JMS 2.0.

See Spring 4 CachingConnectionFactory with JMS 2.0 doesn't properly cache Producers and https://jira.spring.io/browse/SPR-11949

Basically, you need to use at least Spring 4.0.6, or 4.1RC1 where this bug has been fixed.

查看更多
登录 后发表回答