Hello,
When I'm using spring-boot-starter-artemis with org.messaginghub pooled-jms, if I'm stopping the application (or sometimes during the execution) I get:
javax.jms.IllegalStateException: Session is closed
at org.apache.activemq.artemis.jms.client.ActiveMQSession.checkClosed(ActiveMQSession.java:1165) ~[artemis-jms-client-2.6.4.jar:2.6.4]
at org.apache.activemq.artemis.jms.client.ActiveMQSession.setMessageListener(ActiveMQSession.java:315) ~[artemis-jms-client-2.6.4.jar:2.6.4]
at org.messaginghub.pooled.jms.JmsPoolSession.close(JmsPoolSession.java:91) ~[pooled-jms-1.0.6.jar:na]
at org.springframework.jms.support.JmsUtils.closeSession(JmsUtils.java:109) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.clearResources(DefaultMessageListenerContainer.java:1242) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.access$100(DefaultMessageListenerContainer.java:1048) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer.doShutdown(DefaultMessageListenerContainer.java:594) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.shutdown(AbstractJmsListeningContainer.java:244) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.destroy(AbstractJmsListeningContainer.java:184) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.jms.config.JmsListenerEndpointRegistry.destroy(JmsListenerEndpointRegistry.java:251) ~[spring-jms-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:258) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:571) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:543) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1040) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:504) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1033) ~[spring-beans-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1057) ~[spring-context-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1026) ~[spring-context-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:945) ~[spring-context-5.1.10.RELEASE.jar:5.1.10.RELEASE]
If the cache is set to CACHE_CONNECTION
or CACHE_NONE
, I don't get this exception.
Conceptually shouldn't the cache be disable (automatically) when the pool is used?
Comment From: philwebb
Spring Boot doesn't have any knowledge of JmsPoolSession
so I'm not sure we can do anything about this. It looks like an issue in org.messaginghub.pooled.jms.JmsPoolSession
, perhaps it's calling close twice somehow. I'd suggest raising an issue with the pooled-jms team.
Comment From: bigon
My question was a bit about the value of the cache being set to CACHE_AUTO
by default even when spring.artemis.pool.enabled
is set to true.
During my (limited) testing I've never been able to see the number of connection going above 1 (with spring.artemis.pool.max-connections=5
) with the caching enabled. As it's the management is delegated to the pool, that's why I was asking if the caching shouldn't just be disabled completely
Comment From: philwebb
I missed that the CACHE
constants are part of DefaultMessageListenerContainer.
Out current JmsAnnotationDrivenConfiguration
class doesn't have any direct knowledge of Artemis so it would feel a bit odd to configure the cache level based on that property.
@snicoll Do you have any thoughts on this?
Comment From: snicoll
Sorry for the late reply. Spring Boot itself doesn't do anything at the moment and delegate to the default behaviour of the core framework. In the absence of a PlatformTransactionManager
the cache level will be effectively CACHE_CONSUMER
which looks legit to me. The pool is only going to cache the connection but won't cache the Session
or the MessageProducer
used to send replies, if any.
So I don't think caching should be set to NONE for the reason you're using a connection pool. The exception is an entirely different topic though. I wonder if we couldn't be a bit more defensive here. Moving to spring-framework
for further considerations as this is somewhat unrelated to Spring Boot.
@bigon If you can share a minimal sample(github repo or zip) we can run ourselves to reproduce the stacktrace, that would be super helpful.
Comment From: snicoll
Discussing a bit more with @jhoeller we'd like a sample that reproduces this issue please as we consider that this should work and might be an issue elsewhere.
Comment From: bigon
Hello @snicoll
I believe I was able to get the backtrace and the cache/pool behavior with https://start.spring.io/ with the "Apache ActiveMQ Artemis" dependency, so it should be really easy to reproduce
Comment From: snicoll
@bigon sweet. If you don't mind, instructions on how to reproduce it would be very much welcome.
Comment From: bigon
Hello @snicoll,
I finally had the time to look at this again, as said this is an almost non-modified quick-start from https://start.spring.io/
With the code attached here, the number of threads is never going above 1 (while spring.jms.listener.max-concurrency
is set to 5) and I get the javax.jms.IllegalStateException: Session is closed
when stopping the application.
If I uncomment the code in DemoApplication.java
and set the cache to CACHE_CONNECTION
(or to CACHE_NONE
), the number of threads is going to 5 (as I would expect) and I don't get the IllegalStateException
on exit.
Comment From: ymajoros
@snicoll @jhoeller any news on this? Got the same stack trace today.
Comment From: jhoeller
I don't see anything that we can do about this from the core framework side. We defensively catch and log any exceptions thrown within JmsUtils.closeSession
already; I actually wonder where that stacktrace comes from, we only log that at trace level.
Also, we allow for changing the cache level in the listener container. Automatically adapting the cache level isn't really feasible since there is no reliable way to detect a pooled ConnectionFactory, so I'm afraid this will have to be explicitly configured.
As a side note, there is generally no need to configure a listener container with a pooled ConnectionFactory to begin with since it is capable of performing specific resource reuse for its own purposes in any case. A pooled ConnectionFactory is primarily useful for sending purposes via JmsTemplate and co.