BassemH opened a new pull request, #2253:
URL: https://github.com/apache/activemq/pull/2253

   ## Problem
   
   `LocalAndXATransaction.end(xid, TMFAIL)` marks the `TransactionContext` 
`rollbackOnly` so
   that no further work is done in the transaction that has just failed, and
   `ActiveMQSession.send()` refuses to send while that marker is set 
(AMQ-7485). The marker
   is cleared only by `TransactionContext.begin()` and `start(xid, flags)`, 
that is, at the
   next transaction boundary on that context, which matches the stated intent 
of AMQ-7485:
   "failed ended transactions prevent further work till next transaction 
boundary".
   
   In the resource adapter, though, the `TransactionContext` is not transaction 
scoped.
   `ActiveMQManagedConnection` holds it in a `final` field created from the 
physical
   connection, so it lives as long as the pooled connection, and every session 
handed out
   from that managed connection observes it because
   `ManagedTransactionContext.isRollbackOnly()` consults the shared context 
unconditionally:
   
   ```java
   public boolean isRollbackOnly() {
       return sharedContext.isRollbackOnly() || super.isRollbackOnly();
   }
   ```
   
   So when a container returns a managed connection to the pool after a rolled 
back
   transaction and later hands it out for work that is **not** part of a 
transaction, there
   is no next transaction boundary. Nothing clears the marker, and every send 
on that pooled
   connection fails with:
   
   ```
   jakarta.jms.IllegalStateException: transaction marked rollback only
       at org.apache.activemq.ActiveMQSession.send(ActiveMQSession.java:1975)
       at 
org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:329)
   ```
   
   The connection stays unusable for non transacted sends until it happens to 
be enlisted in
   a transaction again. `ManagedConnection.cleanup()` does not reset the 
marker, and because
   `ActiveMQManagedConnectionFactory` does not implement 
`ValidatingManagedConnectionFactory`
   the container cannot detect or evict the affected connection either.
   
   This is easy to hit on a JCA container. IronJacamar's 
`TxConnectionListener.delist()`
   delists with `TMFAIL` whenever the transaction status is 
`STATUS_MARKED_ROLLBACK`, and
   Narayana's `XAResourceRecord.topLevelAbort()` ends the branch with `TMFAIL`, 
so any
   rolled back transaction that touched the RA leaves that pooled connection 
unusable for
   subsequent non transactional sends. We hit this on JBoss EAP 8 / WildFly 
after upgrading
   the client from 5.9.1 to 6.2.4; every `@TransactionAttribute(NOT_SUPPORTED)` 
send in the
   application started failing intermittently, and the reported error mentions 
a transaction
   even though no transaction is involved at the point of failure.
   
   ## Fix
   
   Clear the marker in `LocalAndXATransaction.cleanup()`.
   
   That method is only reached from `ManagedConnection.cleanup()`, which is the 
point where
   the container recycles the physical connection, and it already discards the 
rest of the
   transaction scoped state by delegating to `TransactionContext.cleanup()` 
(which nulls
   `associatedXid` and `transactionId`, but not `rollbackOnly`).
   
   `end(TMFAIL)` sets the marker *after* `setInManagedTx(false)`, so a session 
that took
   part in the failed transaction still sees it. The behaviour AMQ-7485 added, 
and the
   `testSendOnAbortedXATx` test that asserts it, are unchanged.
   
   ## Test
   
   
`JmsXAQueueTransactionTest#testSendOnRecycledManagedConnectionAfterAbortedXATx` 
aborts an
   XA transaction with `TMFAIL`, recycles the managed connection via
   `ManagedConnection.cleanup()`, then obtains a fresh handle and sends outside 
of any
   transaction.
   
   Without the change it fails:
   
   ```
   junit.framework.AssertionFailedError: recycled managed connection must not 
stay rollbackOnly
       at org.apache.activemq.ra.JmsXAQueueTransactionTest
          
.testSendOnRecycledManagedConnectionAfterAbortedXATx(JmsXAQueueTransactionTest.java:205)
   ```
   
   With the change the whole `activemq-ra` module passes:
   
   ```
   Tests run: 119, Failures: 0, Errors: 0, Skipped: 2
   ```
   
   which includes `testSendOnAbortedXATx`, `JmsXARollback2CxTransactionTest`,
   `FailoverManagedConnectionTest` and `FailoverManagedClusterTest` (the 
failover with
   pending acks scenario that AMQ-5854 originally introduced the marker for).
   
   The change also cherry-picks cleanly onto `activemq-6.2.x`.
   
   I was not able to open a JIRA issue for this (ASF JIRA no longer allows self 
service
   account creation), so the commit carries no issue key. Happy to add one if a 
committer
   creates the issue.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to