]
Tom Jenkinson commented on JBTM-2394:
-------------------------------------
In that scenario the reaper would attempt to rollback the XAR a number of times (detecting
the wedged resource) and finally it would give up trying to call rollback on the XAR and
just call setRollbackOnly on the TX. I can say that the transaction reaper has been
working in this manner successfully with many resource managers over the years.
The reason we added JBTM-2342 is to assist with JPA which specifically is not thread-safe
and the app server integration is required to call EntityManager.close() during
afterCompletion(). You mentioned that you cannot use reaper thread names - this is
entirely true and was considered during discussions on our forum regarding JBTM-2342. It
was determined that this would not work in all scenarios as it is possible that a timed
out transaction in a remote parent coordinator _may_ fire before the reaper anyway and in
that case the rollback would come via (for example) Jacorb RequestProcessors and would be
undetectable as a concurrent call. Hence JBTM-2342 provides an SPI to assist further.
Alternatively, it would be possible for an XAResource implementation to detect concurrent
access and use multiple (internal) connections to the database if that is a requirement of
the implementation.
I honestly feel that you will get better advice by discussing this on the forum. The
transaction manager component (so Narayana) is not intended to be aware of connections. A
caller invokes TX::enlist(XAResource). Callers do not provide us with
"connections" or factories (I quote the word to signify it draw out how these
can be JDBC/JMS/etc) to attempt to obtain an XAR from.
Finally, as you point out the recovery manager is able to obtain XAR from helpers but the
recovery manager has a very specific purpose and is not intended for this use case. Not
that I would advocate a change in this area but if you were considering such a thing,
determining which of the XAR registered with the recovery manager should be used to issue
the rollback would be impossible as it stands.
Transaction Reaper "abuses" in-use connection, leading to
RPC protocol corruption
---------------------------------------------------------------------------------
Key: JBTM-2394
URL:
https://issues.jboss.org/browse/JBTM-2394
Project: JBoss Transaction Manager
Issue Type: Bug
Reporter: Christian von Kutzleben
Assignee: Tom Jenkinson
The scenario is as follows:
An regular JBoss application thread uses the connection associated with an XAResource for
it's work with the database backend. Start(xid) had been invoked, which means, the
associated connection is "switched" to that xid. After finishing work, the
regular JBoss application thread would eventually call end(xid, TMSUCCESS).
The application executes a query that takes longer than the configured timeout.
The work with the database is done via database specific RPC invocations, caused by a
enterprise bean (which uses the JPA API and the JPA implementation eventually talks to the
database via the database protocol).
The (lower-level) connection is a TCP/IP connection, and
the RPC protocol if of the form: "send data to server, then wait for server
reply"
At this point it should be clear, that the TCP/IP connection should not be shared by
another thread whilst in the middle of an RPC invocation, because neither does the
database server expect any data at this moment on this particular TCP/IP connection nor
does it work, that then 2 threads wait on the same socket to receive a reply. (E.g. a
ClosedByInterruptException is likely, there might be other error though, depending how
wrong data is interpreted, e.g. BufferUnderflowException).
Unfortunately, this is exactly the behavior of the JBoss "Transaction Reaper"
thread, that uses the very same XAResource, that had been used by the regular JBoss
application thread and is currently associated to a connection, "switched" to
the current xid.
By definition of the XA specification, any other XAResource could be used to terminate
that transaction branch, and it would be fine, if the transaction reaper thread would use
any XAResource (regular one, or one from our recovery module) to do that.
This is a conceptual flaw of the transaction reaper implementation, and we can't
implement a workaround (except extremely silly things like reaper thread recognition by
comparing thread names ...)
We could synchronize access to the TCP/IP connection, to not allow another thread
communication, while another thread is active doing so, however, that kind of defeats the
purpose of the reaper thread, as it would be blocked indefinitely.