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