artemis 2.19 / spring boot 2.7.8
I searched why a native broker connection does not recover fast after restarting broker, but takes 10 min to recover.
I found
spring.jms.cache.enable=false solves the problem
switching it off by property is no option since I use JMS template in same component.
Javadoc writes:
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.
I assume autoconfiguration shoud use unwrapped connection factory for listener container.
Comment From: wilkinsona
OSS support for Spring Boot 2.7.x has ended so I'm afraid this won't change in Spring Boot 2.x.
If you want to use a caching connection factory with your JMS template but not with your message listener container, you could define either the template or the listener container yourself. The latter is probably the easier of the two:
@Bean
DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
DefaultJmsListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, ((CachingConnectionFactory)connectionFactory).getTargetConnectionFactory());
return factory;
}
Spring Boot 3.x uses Spring Framework 6.x where the javadoc has been amended and the note softened quite a bit. That said, it still leans towards not using a CachingConnectionFactory with a listener container.
@jhoeller, what would you recommend here for Boot 3? I doubt that we'd change this in a maintenance release but we could consider unwrapping any caching connection factory in a new minor.
Comment From: jschmied
Yes, unwrapping is easy. It just breaks reconnecting after broker restart badly.
Comment From: jschmied
I just reviewed the javadoc change. The change of documentation relating to dynamic scaling might be right. What should be stressed: the CachingConnectionFactory breaks (might be depending on type underlying ConnectionFactory) recovering from broker outage. This is clearly reproducable. In our case it affected the system badly leading to outage of our production system and unessesary downtime affecting our customers.
Comment From: jhoeller
For listener recovery, it is indeed recommendable to configure the message listener containers with the target ConnectionFactory directly, letting them use one Connection per listener container. It's a tradeoff with the number of Connections in the overall application which should be fine in many scenarios, giving full responsibility to each listener container in terms of local recovery.
With a high number of listener containers, I'd consider Connection reuse in the setup but even that does not have to be a global CachingConnectionFactory, could also be a SingleConnectionFactory shared among the listener containers - whereas for JmsTemplate usage, there could still be a separate CachingConnectionFactory for template operations only.
Customizing the DefaultJmsListenerContainerFactory should do the trick for the time being. For Boot 3.3, we could consider a revised setup strategy by default indeed.
Comment From: snicoll
Brainstorming with Juergen, we need to make sure to configure the DMLC with the target/native ConnectionFactory rather than a caching ConnectionFactory that is more suited to JmsTemplate. We have two candidates for wrapping the native broker connection factory: CachingConnectionFactory and JmsPoolConnectionFactory.
The easiest would be to be opinionated in our own auto-configuration, extracting the target ConnectionFactory. However, since users may want to create their own DefaultJmsListenerContainerFactory we should provide an API that does the unwrap so that they don't have to do that themselves.
Comment From: graben
It seems that this change is causing a problem with Narayana integration because the unwrapped ConnectionFactory is not enlisted in the transaction any more.
Setup of JMS message listener invoker failed for destination 'someQueue' - trying to recover. Cause: Session's XAResource has not been enlisted in a distributed transaction.
Comment From: snicoll
@graben the link between this commit and the exception you've shared is unclear. If you believe you've found an issue in Spring Boot, please create a separate issue with a small sample that we can use to reproduce it.
Comment From: graben
@snicoll: I'll try to build a simple error case. But the issue is quite simple ConnectionFactoryUnwrapper.unwrap(connectionFactory)) in class JmsAnnotationDrivenConfiguration does unwrap the Narayana integration "magic" :-)