11

I was reading spring documentation on DefaultMessageListenerContainer

It says "Note: Don't use Spring's CachingConnectionFactory in combination with dynamic scaling. Ideally, don't use it with a message listener container at all, since it is generally preferable to let the listener container itself handle appropriate caching within its lifecycle. Also, stopping and restarting a listener container will only work with an independent, locally cached Connection - not with an externally cached one."

Could anybody explain why?

Gary Russell
  • 131,626
  • 14
  • 99
  • 125
EmeraldTablet
  • 692
  • 3
  • 10
  • 28

1 Answers1

15
  1. You really don't need to cache sessions for listener containers because the sessions are long lived; caching is very beneficial for frequent short use, such as with the JmsTemplate.
  2. The problem is really when cacheConsumers = true (the default). When using dynamic scaling and a listener is stopped, the session is returned to the cache but the broker doesn't know that nobody will actually consume from that session, so you are stuck with messages sitting in the cache that won't be read until that session happens to be reused when the volume increases.

Note: if you wish a JmsTemplate running on the container thread to participate in a container transaction, you should use a CachingConnectionFactory so the producers can be cached, but you should disable caching consumers in the factory if you have variable concurrency.

Gary Russell
  • 131,626
  • 14
  • 99
  • 125
  • Thanks for the response and explanation Gary. – EmeraldTablet Feb 25 '14 at 09:25
  • Gary just curious if a **listener container** or a **DefaultMessageListenerContainer** should not use a SingleConnectionFactory too. Since it is the superclass of the CachingConnectionFactory class. – Manuel Jordan Aug 10 '14 at 23:47
  • Manual, no, that's ok; the problem is with caching consumers when using variable concurrency in the container; you can end up with a live consumer "stuck" in the cache. – Gary Russell Aug 11 '14 at 12:19
  • Ok understood, I can use SingleConnectionFactory with a DefaultMessageListenerContainer. I have the problem when I have two DefaultMessageListenerContainer with setSubscriptionDurable true, therefore I need set two differents values for setClientId and setDurableSubscriptionName values. **If I use SingleConnectionFactory or CachingConnectionFactory** always I get "Could not refresh JMS Connection for destination 'topic://branch' - retrying in 5000 ms. Cause: setClientID call not supported on proxy for shared Connection. Set the 'clientId' property on the SingleConnectionFactory instead." – Manuel Jordan Aug 12 '14 at 15:29
  • I around this problem using the ConnectionFactory directly for each DefaultMessageListenerContainer. If you know a better way, pls let me know. – Manuel Jordan Aug 12 '14 at 15:30
  • Well, per the JMS spec, the `clientId` is a property of the connection so you can't share a single connection across different clientIds. The proxy does allow multiple containers to use the same clientId. [See this code](https://github.com/spring-projects/spring-framework/blob/master/spring-jms/src/main/java/org/springframework/jms/connection/SingleConnectionFactory.java#L494). You can still use `SingleConnectionFactory` but you need one for each unique `clientId`; they can wrap the same vendor connection factory (and the single connections can be shared for other uses - e.g. `JmsTemplate`). – Gary Russell Aug 12 '14 at 15:46
  • Hi Gary .. could you please elaborate on point-2 in your answer above or probably provide a link/reference? – Vimal Jain Nov 13 '15 at 10:01
  • 4
    I am not sure how much more elaboration you need. Let's say you have 5 consumers, and the workload drops so the container stops a consumer. If caching is in place, the consumer is left open and put in a cache instead of closing it. Since the broker doesn't know anything about this, he thinks it's still consuming so happily sends up to prefetch messages to it. Since the container is not using that consumer, nobody will see those messages until the workload in the other 4 containers increases such that it decides another consumer is needed and the cached consumer is again used. – Gary Russell Nov 13 '15 at 13:30
  • @GaryRussell, regarding point 2, if dynamic scaling is not used, does that mean caching consumer will not be an issue? Does it provide more performance gain if consumer is cached (without dynamic scaling)? Regarding point 1- So sessions do not need to be cached, does that mean we can do CachingConnectionFactory.setSessionCacheSize(0) to turn it off? Does it matter if it is left to be default value, which is 1. Another question, If a fixed number of listeners used, for example 2, does that mean there will be 2 long lived sessions? – sarahTheButterFly May 12 '17 at 02:34
  • You should really ask a new question rather than commenting on an old one from more than 3 years ago. The admins here don't like extended commentary. As long as you don't have variable concurrency, it doesn't matter. Yes, there will be 2 long-lived sessions in that case. – Gary Russell May 12 '17 at 03:07
  • @GaryRussell Thank you for the reply. I will do that next time. – sarahTheButterFly May 12 '17 at 04:18