Search code examples
springspring-jms

Prevent use of CachingConnectionFactory with DefaultJmsListenerContainerFactory


I am working on a brand new project in which I need to have listeners that will consume messages from several queues (no need to have producer for now).

Starting from scratch, I am using the last Spring JMS version (4.1.2).

Here is an extract of my configuration file:

<bean id="cachedConnectionFactory" 
          class="org.springframework.jms.connection.CachingConnectionFactory"
        p:targetConnectionFactory-ref="jmsConnectionFactory"
        p:sessionCacheSize="3" />

<bean id="jmsListenerContainerFactory"
          class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"
          p:connectionFactory-ref="cachedConnectionFactory"
          p:destinationResolver-ref="jndiDestinationResolver"
          p:concurrency="3-5"
          p:receiveTimeout="5000" />

But I think I may be wrong since DefaultJmsListenerContainerFactory will build regular DefaultMessageListenerContainerS. And, as stated in the doc, CachingConnectionFactory should not be used with a message listener container...

  • Even if I am using the new Spring 4.1 DefaultJmsListenerContainerFactory class the answer from post is still valid (cacheConsumers = true can be an issue + don't need to cache sessions for listener containers because the sessions are long lived) , right?
  • Instead of using the CachingConnectionFactory, I should use the SingleConnectionFactory (and not directly the broker implementation one)?
  • If the SingleConnectionFactory class should indeed be used, is the "reconnectOnException" property should be set to true (as it is done in the CachingConnectionFactory) or does the new "setBackOff" method (from DefaultJmsListenerContainerFactory) deals with the same kind of issues?

Thanks for any tips


Solution

    • Correct.
    • There's not really much benefit in using a SingleConnectionFactory unless you want to share a single connection across multiple containers; the DMLC will use a single connection from the vendor factory by default for all consumer threads (cacheLevel >= CACHE_CONNECTION), unless a TransactionManager is configured.
    • The container(s) will handle reconnection - even before the 'new' backOff property - backOff just adds more sophistication to the reconnection algorithm - it used to just retry every n seconds (5 by default).

    As stated in the answer you cited, it's ok to use a CCF as long as you disable consumer caching.

    Correction: Yes, when using the SingleConnectionFactory, you do need to set reconnectOnException to true in order for the container to properly recover its connection. Otherwise, it simply hands out the stale connection.