Craig Day opened SPR-2370 and commented

If a connection is ever closed underneath a DefaultMessageListenerContainer, the container will never recover. The initResourcesIfNecessary() method in the internal AsyncMessageListenerInvoker continues to use the connection returned by the getConnection() method (which is not a call that ends up in connectionFactory.createConnection()).


Affects: 2.0 RC1, 2.0 RC2

Comment From: spring-projects-issues

Juergen Hoeller commented

FYI, this is already partly solved in CVS HEAD through configurable caching of JMS resoures now: DefaultMessageListenerContainer by default reobtains all JMS resource handles in case of an external transaction manager specified (through the "transactionManager" property). So in the latter case, a fresh Connection will be picked up from the pool for each transaction. This was necessary to always obtain a transactional resource (even on JBoss, which doesn't auto-enlist JMS Sessions unless the Connection has been obtained within the current transaction's scope); it just has the side effect of bypassing the need for Connection recovery in the first place.

Without an external transaction manager, the default is still to cache all JMS resources. Reobtaining can be enforced through the "cacheLevel"/"cacheLevelName" property there, specifying CACHE_NONE (instead of the default CACHE_CONSUMER). However, this might lead to inefficient use of JMS resources, in particular outside of a J2EE environment. For that reason, I'll try to build Connection recovery in even for a cached Connection (as per your original intent), analogous to the existing recovery for cached JMS Sessions and MessageConsumers.

Juergen

Comment From: spring-projects-issues

Craig Day commented

Juergen, sorry for my confusion, but are you saying that in RC2, DefaultMessageListenerContainer, when used with a transactionManager should already reobtain connections? - or is this the change you have made in CVS? My test case used a DefaultMessageListenerContainer with Springs JMSTransactionManager and I still saw the issue. Just want to clarify.

Comment From: spring-projects-issues

Juergen Hoeller commented

Maybe I wasn't entirely clear there: In RC2, the Connection always got cached and never refreshed. In CVS HEAD, the latest nightly snapshots and the just-around-the-corner RC3, full Connection recovery is available now, for both the JTA and the non-JTA case (with different characteristics, but the same general effect).

Juergen

Comment From: aayarushin

@jhoeller , I have stumbled upon a problem that seems related or same. Namely, DefaultMessageListenerContainer does not recover after restart of server holding the queues.

I am using Apache Camel 2.13.2.

Can you tell if this is something that can be handled in Camel/Spring, in client code or otherwise can be mitigated by clustering solutions?

The log tells: ... 2020-04-16 13:13:14,806 Camel (camel-1) thread #11 - JmsConsumer[NHNTESTServiceBus/8134967_error] WARN DefaultJmsMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'NHNTESTServiceBus/8134967_error' - trying to recover. Cause: Closed ...

and then immediately: ... javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLException: java.net.SocketException: Connection reset at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1533) at sun.security.ssl.AppInputStream.read(AppInputStream.java:106) at java.io.InputStream.read(InputStream.java:101) at org.apache.qpid.amqp_1_0.client.TCPTransportProvier.doRead(TCPTransportProvier.java:178) at org.apache.qpid.amqp_1_0.client.TCPTransportProvier.access$000(TCPTransportProvier.java:38) at org.apache.qpid.amqp_1_0.client.TCPTransportProvier$1.run(TCPTransportProvier.java:138) at java.lang.Thread.run(Thread.java:748) Caused by: javax.net.ssl.SSLException: java.net.SocketException: Connection reset at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1903) at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1867) at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1812) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:128) at org.apache.qpid.amqp_1_0.framing.ConnectionHandler$BytesOutputHandler.processBytes(ConnectionHandler.java:466) at org.apache.qpid.amqp_1_0.framing.ConnectionHandler$HeaderBytesSource.getBytes(ConnectionHandler.java:340) at org.apache.qpid.amqp_1_0.framing.ConnectionHandler$SequentialBytesSource.getBytes(ConnectionHandler.java:374) at org.apache.qpid.amqp_1_0.framing.ConnectionHandler$BytesOutputHandler.run(ConnectionHandler.java:450) ... 1 more Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:210) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.security.ssl.InputRecord.readFully(InputRecord.java:465) at sun.security.ssl.InputRecord.read(InputRecord.java:503) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:750) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) ... 5 more ...

Thank you!