XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 7.3.0.Final
    • 5.12.7.Final, 5.13.1.Final, 6.0.3.Final, 7.1.0.Final, 7.2.2.Final
    • JTA
    • Hide

      See below.

      Mark session as rollback.

      Try and close session and connection.

       

      You should see STATUS_MARKED_ROLLBACK followed by the TransactionHelper throwing an Exception.

      Show
      See below. Mark session as rollback. Try and close session and connection.   You should see STATUS_MARKED_ROLLBACK followed by the TransactionHelper throwing an Exception.
    • User Experience
    • Fixes a connection and session leak in the Narayana JMS integration component when the transaction is marked rollback only.

      Note when running in combination with Spring and or Spring Boot and ArtemisMQ. This behaviour has occurs with ActiveMQ and TibcoMQ. Does not occur with BTM and WebSphere TXM. We've tested versions from '5.12.7.Final' onwards, with JDK 11/17 and 21.

       

      When the PlatformTransactionManager#rollback(txStatus) is called, and the session has already been marked for rollback, the `SessionClosingSynchronization` cannot be registered with the transactionHelper. We see the following stacktrace:

      2025-08-22 16:49:25,527 TRACE [JmsFFListener[1]] ats.jta - TransactionImple.getStatus: jakarta.transaction.Status.STATUS_MARKED_ROLLBACK
      2025-08-22 16:49:25,532 TRACE [JmsFFListener[1]] ats.jta - TransactionImple.registerSynchronization - Class: class org.jboss.narayana.jta.jms.SessionClosingSynchronization HashCode: 188964741 toString: org.jboss.narayana.jta.jms.SessionClosingSynchronization@b435f85
      2025-08-22 15:40:06,882 WARN [JmsFFListener[1]] ats.jta - ARJUNA016124: Failed to register synchronization
      jakarta.transaction.RollbackException: ARJUNA016083: Cannot register synchronization because the transaction is in aborted state
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronizationImple(TransactionImple.java:381) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronization(TransactionImple.java:362) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at org.jboss.narayana.jta.jms.TransactionHelperImpl.registerSynchronization(TransactionHelperImpl.java:43) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at org.jboss.narayana.jta.jms.SessionProxy.close(SessionProxy.java:74) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at org.springframework.jms.connection.JmsResourceHolder.closeAll(JmsResourceHolder.java:286) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:458) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:419) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.ResourceHolderSynchronization.beforeCompletion(ResourceHolderSynchronization.java:79) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCompletion(TransactionSynchronizationUtils.java:138) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(AbstractPlatformTransactionManager.java:996) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:881) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:866) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.frankframework.jta.SpringTxManagerProxy.rollback(SpringTxManagerProxy.java:80) ~[frankframework-core-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.rollbackOnException(AbstractPollingMessageListenerContainer.java:421) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:249) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.frankframework.jms.IbisMessageListenerContainer.receiveAndExecute(IbisMessageListenerContainer.java:112) ~[frankframework-messaging-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1420) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1294) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.frankframework.threading.ThreadNamingTaskDecorator.lambda$0(ThreadNamingTaskDecorator.java:36) ~[frankframework-core-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
      at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
      at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]

      Moments later the next stacktrace occurs:

      2025-08-22 16:49:35,252 TRACE [JmsFFListener[1]] ats.jta - TransactionImple.getStatus: jakarta.transaction.Status.STATUS_MARKED_ROLLBACK
      2025-08-22 16:49:35,252 TRACE [JmsFFListener[1]] ats.jta - TransactionImple.registerSynchronization - Class: class org.jboss.narayana.jta.jms.ConnectionClosingSynchronization HashCode: 165787659 toString: org.jboss.narayana.jta.jms.ConnectionClosingSynchronization@9e1b80b
      2025-08-22 16:49:35,252 WARN [JmsFFListener[1]] ats.jta - ARJUNA016124: Failed to register synchronization
      jakarta.transaction.RollbackException: ARJUNA016083: Cannot register synchronization because the transaction is in aborted state
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronizationImple(TransactionImple.java:381) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronization(TransactionImple.java:362) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at org.jboss.narayana.jta.jms.TransactionHelperImpl.registerSynchronization(TransactionHelperImpl.java:43) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at org.jboss.narayana.jta.jms.ConnectionProxy.close(ConnectionProxy.java:102) ~[narayana-jta-7.2.2.Final.jar:7.2.2.Final (revision: 405c52)]
      at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?]
      at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?]
      at org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy$TransactionAwareConnectionInvocationHandler.invoke(TransactionAwareConnectionFactoryProxy.java:296) ~[spring-jms-6.2.8.jar:6.2.8]
      at jdk.proxy4/jdk.proxy4.$Proxy187.close(Unknown Source) ~[?:?]
      at org.springframework.jms.connection.ConnectionFactoryUtils.releaseConnection(ConnectionFactoryUtils.java:80) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.connection.JmsResourceHolder.closeAll(JmsResourceHolder.java:293) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:458) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:419) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.ResourceHolderSynchronization.beforeCompletion(ResourceHolderSynchronization.java:79) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCompletion(TransactionSynchronizationUtils.java:138) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(AbstractPlatformTransactionManager.java:996) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:881) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:866) ~[spring-tx-6.2.8.jar:6.2.8]
      at org.frankframework.jta.SpringTxManagerProxy.rollback(SpringTxManagerProxy.java:80) ~[frankframework-core-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.rollbackOnException(AbstractPollingMessageListenerContainer.java:421) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:249) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.frankframework.jms.IbisMessageListenerContainer.receiveAndExecute(IbisMessageListenerContainer.java:112) ~[frankframework-messaging-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1420) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1294) ~[spring-jms-6.2.8.jar:6.2.8]
      at org.frankframework.threading.ThreadNamingTaskDecorator.lambda$0(ThreadNamingTaskDecorator.java:36) ~[frankframework-core-9.2.0-SNAPSHOT.jar:9.2.0-SNAPSHOT]
      at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
      at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
      at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] 

       

       

      This results in 2 sessions being leaked.

      I've experimented with a simple try/catch around the `transactionHelper.registerSynchronization` methods, which closes the session directly (in case there is an exception) to mitigate this issue. Not sure how you wish to tackle this issue but one way or another the session and connection needs to be closed.

              niels@wearefrank.nl Niels Meijer
              niels@wearefrank.nl Niels Meijer
              Votes:
              1 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: