I'm looking at a scenario where the Enterprise Information System is expecting that it is notified with TMFAIL on the connection that actually had the error occur on it. Currently IronJacamar just "disassociates" (makes sure that afterCompletion is "cancelled") the transaction with the connection listener, and kills it afterwards.
The scenario basically looks like
ut.begin() xar = c.getXAResource(); tx.enlistResource(xar); ... tx.delistResource(xar, TMFAIL);
The same connection listener will only be enlisted once per transaction, so there are no multiple Xid's associated with it (unless Narayana interleaving does something in that area).
However, in the above case Narayana allows for a ut.commit() - e.g.
ut.begin(); xar = c.getXAResource(); tx.enlistResource(xar); ... tx.delistResource(xar, TMFAIL); ut.commit();
TMFAIL marks the transaction branch as rollback, but that doesn't seem to be propagated to the overall status of the transaction in this case.
So, does Narayana keep track of the status for each XAResource <-> Xid, and decides the outcome based on the last Xid "status" for each XAResource ?
I have added the TMFAIL on failure interaction here - Send TMFAIL and do setRollbackOnly before connection is killed · jesperpedersen/ironjacamar@76a6650 · GitHub - and explicit set the MARK_FOR_ROLLBACK here - Send TMFAIL and do setRollbackOnly before connection is killed · jesperpedersen/ironjacamar@76a6650 · GitHub as DELIST_RESOURCE isn't necessary enabled. Doing tx.setRollbackOnly() should be safe, as we know the connection listener had a fatal error occur on it, and it will be killed shortly after, e.g. in the method calling haltCatchFire().
I think the above case should do a RollbackException, but I may have overlooked some hidden details The XA spec seems to be most clear about this:
The portion of work has failed. A resource manager might choose to mark a
transaction branch as rollback-only at this point. In fact, a transaction manager
does so for the global transaction. If a resource manager chooses to do so also,
xa_end() returns one of the [XA_RB∗] values. TMFAIL cannot be used in
conjunction with either TMSUSPEND or TMSUCCESS.
Thoughts on the matter would be great !