org.springframework.jms.connection.SynchedLocalTransactionFailedException: Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen

Spring JIRA | Torsten Keim | 4 years ago
  1. 0

    We would like to execute an insert via JPA and an enqueue to an Oracle AQ in one local shared oracle transaction. As explained in "4.3. Configuring the Connection Factory to use the same local transaction as your data access code." our spring configuration looks like: <orcl:aq-jms-connection-factory id="connectionFactory" use-local-data-source-transaction="true" connection-factory-type="QUEUE_CONNECTION" data-source="dataSource" /> We use JmsTemplate for enqueueing and we set its member sessionTransacted to true, because the javadoc says: 'Setting this flag to "true" will use a short local JMS transaction when running outside of a managed transaction, and a synchronized local JMS transaction in case of a managed transaction (other than an XA transaction) being present. The latter has the effect of a local JMS transaction being managed alongside the main transaction (which might be a native JDBC transaction), with the JMS transaction committing right after the main transaction.' We set a breakpoint in JpaTransactionManager.doCommit(DefaultTransactionStatus) line: 512 and could see that this statement indeed causes the Oracle transaction to be committed, i.e. the inserted row and the queue entry could both be seen from an external sqlplus session. So the sharing of the same Oracle transaction works. But then we come to another breakpoint at: AQjmsSession.commit() line: 1009 JmsResourceHolder.commitAll() line: 181 ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(JmsResourceHolder) line: 404 ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ResourceHolder) line: 1 ConnectionFactoryUtils$JmsResourceSynchronization(ResourceHolderSynchronization<H,K>).afterCommit() line: 79 TransactionSynchronizationUtils.invokeAfterCommit(List<TransactionSynchronization>) line: 133 TransactionSynchronizationUtils.triggerAfterCommit() line: 121 JpaTransactionManager(AbstractPlatformTransactionManager).triggerAfterCommit(DefaultTransactionStatus) line: 950 JpaTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus) line: 796 JpaTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 723 and this will throw the following exception: org.springframework.jms.connection.SynchedLocalTransactionFailedException: Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:407) at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:1) at org.springframework.transaction.support.ResourceHolderSynchronization.afterCommit(ResourceHolderSynchronization.java:79) at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:133) at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:121) at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCommit(AbstractPlatformTransactionManager.java:950) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:796) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147) .... Caused by: javax.jms.IllegalStateException: JMS-131: Session ist geschlossen at oracle.jms.AQjmsError.throwIllegalStateEx(AQjmsError.java:471) at oracle.jms.AQjmsSession.checkSessionStarted(AQjmsSession.java:4736) at oracle.jms.AQjmsSession.commit(AQjmsSession.java:1009) at org.springframework.jms.connection.JmsResourceHolder.commitAll(JmsResourceHolder.java:181) at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:404) ... 58 more So the problem is that the JmsTemplate is not aware of the fact that the Oracle transaction is shared by JPA and JMS and tries to commit an already committed transaction.

    Spring JIRA | 4 years ago | Torsten Keim
    org.springframework.jms.connection.SynchedLocalTransactionFailedException: Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen
  2. 0

    We would like to execute an insert via JPA and an enqueue to an Oracle AQ in one local shared oracle transaction. As explained in "4.3. Configuring the Connection Factory to use the same local transaction as your data access code." our spring configuration looks like: <orcl:aq-jms-connection-factory id="connectionFactory" use-local-data-source-transaction="true" connection-factory-type="QUEUE_CONNECTION" data-source="dataSource" /> We use JmsTemplate for enqueueing and we set its member sessionTransacted to true, because the javadoc says: 'Setting this flag to "true" will use a short local JMS transaction when running outside of a managed transaction, and a synchronized local JMS transaction in case of a managed transaction (other than an XA transaction) being present. The latter has the effect of a local JMS transaction being managed alongside the main transaction (which might be a native JDBC transaction), with the JMS transaction committing right after the main transaction.' We set a breakpoint in JpaTransactionManager.doCommit(DefaultTransactionStatus) line: 512 and could see that this statement indeed causes the Oracle transaction to be committed, i.e. the inserted row and the queue entry could both be seen from an external sqlplus session. So the sharing of the same Oracle transaction works. But then we come to another breakpoint at: AQjmsSession.commit() line: 1009 JmsResourceHolder.commitAll() line: 181 ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(JmsResourceHolder) line: 404 ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ResourceHolder) line: 1 ConnectionFactoryUtils$JmsResourceSynchronization(ResourceHolderSynchronization<H,K>).afterCommit() line: 79 TransactionSynchronizationUtils.invokeAfterCommit(List<TransactionSynchronization>) line: 133 TransactionSynchronizationUtils.triggerAfterCommit() line: 121 JpaTransactionManager(AbstractPlatformTransactionManager).triggerAfterCommit(DefaultTransactionStatus) line: 950 JpaTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus) line: 796 JpaTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 723 and this will throw the following exception: org.springframework.jms.connection.SynchedLocalTransactionFailedException: Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:407) at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:1) at org.springframework.transaction.support.ResourceHolderSynchronization.afterCommit(ResourceHolderSynchronization.java:79) at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:133) at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:121) at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCommit(AbstractPlatformTransactionManager.java:950) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:796) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147) .... Caused by: javax.jms.IllegalStateException: JMS-131: Session ist geschlossen at oracle.jms.AQjmsError.throwIllegalStateEx(AQjmsError.java:471) at oracle.jms.AQjmsSession.checkSessionStarted(AQjmsSession.java:4736) at oracle.jms.AQjmsSession.commit(AQjmsSession.java:1009) at org.springframework.jms.connection.JmsResourceHolder.commitAll(JmsResourceHolder.java:181) at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:404) ... 58 more So the problem is that the JmsTemplate is not aware of the fact that the Oracle transaction is shared by JPA and JMS and tries to commit an already committed transaction.

    Spring JIRA | 4 years ago | Torsten Keim
    org.springframework.jms.connection.SynchedLocalTransactionFailedException: Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen

    Root Cause Analysis

    1. org.springframework.jms.connection.SynchedLocalTransactionFailedException

      Local JMS transaction failed to commit; nested exception is javax.jms.IllegalStateException: JMS-131: Session ist geschlossen

      at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit()
    2. Spring Framework
      ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit
      1. org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:407)
      2. org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.processResourceAfterCommit(ConnectionFactoryUtils.java:1)
      2 frames
    3. Spring Tx
      TransactionTemplate.execute
      1. org.springframework.transaction.support.ResourceHolderSynchronization.afterCommit(ResourceHolderSynchronization.java:79)
      2. org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:133)
      3. org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:121)
      4. org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCommit(AbstractPlatformTransactionManager.java:950)
      5. org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:796)
      6. org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
      7. org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:147)
      7 frames