Bug #72890 Java jdbc driver returns incorrect return code when it's part of XA transaction
Submitted: 5 Jun 2014 14:46 Modified: 22 Nov 2014 0:15
Reporter: Ondrej Chaloupka Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version:5.1.28 OS:Any
Assigned to: Filipe Silva CPU Architecture:Any
Tags: jdbc xa

[5 Jun 2014 14:46] Ondrej Chaloupka
Description:
The jdbc driver for java returns incorrect return code '0' in thrown exception. This is incorrect when resource is part of the global xa transaction.

The test scenario is based on halting connection to database - in this case before the prepare is called on database XAResource - then the jdbc driver returns the invalid exception code

code:0: com.mysql.jdbc.jdbc2.optional.MysqlXAException: Communications link failure

How to repeat:
Kill database before the prepare is called on resource which is part of global transaction and check the error code which is returned by jdbc driver in such situation.

Suggested fix:
The correct return code should be XAER_RMFAIL as the RM is unavailable at the point of connection failure (http://docs.oracle.com/javase/7/docs/api/javax/transaction/xa/XAException.html#XAER_RMFAIL).
[5 Jun 2014 18:02] Mark Matthews
I'd be leery of using XA in production until this long-standing bug is fixed:

http://bugs.mysql.com/bug.php?id=12161
[11 Jun 2014 23:42] Filipe Silva
Hi Ondrej,

Thank you for this bug report.

I'm not being able to reproduce this behavior, please provide a full stack trace and, if possible, a simple test code or at least a little more detail on how to hit this issue. Thank you.
[12 Jun 2014 12:44] Ondrej Chaloupka
Hi,

I'm sorry but currently I do not have any simple reproducer which I could easily share. 
I run JBoss EAP 6.2 server with Narayana transaction manager. The stack trace is attached in file.

My test scenario is following - using 2 xa datasources, one DB datasource and other non-DB datasource
1) prepare db XA (XAResource.prepare is processed from java side)
2) stop db connection (connection to database is halted)
3) prepare non-db XA (prepare is run without problem as connection to db is not needed)
4) commit db XA (XAResource.commit - connection is down - error code for MySQL is 0; XAException.XAER_RMFAIL for Oracle, XAException.XAER_RMERR for PostgreSQL)
5) TM behaves in dependence of returned XAException error code

Please, let me know, whether I should add better explanation or more details.

Thank you
Ondra
[12 Jun 2014 12:45] Ondrej Chaloupka
Stack trace where MySQL returns XAException error code 0

Attachment: mysql-error-code-0-stack.txt (text/plain), 7.55 KiB.

[12 Jun 2014 22:58] Filipe Silva
Hi Ondrej,

This bug was verified from code review.

Still, I'm not sure if the return error code should be XAException.XAER_RMFAIL or XAException.XAER_RMERR. I'm inclined to XAException.XAER_RMERR but I'll clarify this before applying any fix. From your observations I guess you'll be fine with any, right?

Thanks,
[13 Jun 2014 6:36] Ondrej Chaloupka
I think that the correct return code is XAException.XAER_RMFAIL in this case.

From docs:
XAER_RMFAIL
Resource manager is unavailable.
XAER_RMERR
A resource manager error has occurred in the transaction branch.

My interpretation is that resource manager is unavailable here and so there is no problem in transaction branch on database side. When connection is up TM could easily contact database again. In case of XAER_RMERR TM does not know what happened and so admin will need to fix such transaction manually afterwards.
I personally think that PostgreSQL should return the XAER_RMFAIL as well.
[17 Jul 2014 17:08] Daniel So
Added the following entry to the Connector/J 5.1.32 changelog:

"Connector/J returned the incorrect return code “0” for a thrown exception when the failure happened in the context of a global XA transaction. With this fix, Connector/J now wraps any unexpected exception in an XAException in that case and returns the error code XAER_RMFAIL."
[22 Nov 2014 0:15] Ondrej Chaloupka
Hi,

I would like just point out that despite the fact the return code XAER_RMFAIL is returned the behaviour of database is not correct. It seems that this is tightly connected with http://bugs.mysql.com/bug.php?id=12161. 
Connection is down, jdbc driver returns XAER_RMFAIL which dictates to transaction manager to commit. Transaction manager tries to commit during recovery but the try ends with error returned by mysql side. At the end the value is not changed and is maintained as was before start of transaction.

I would like to note that as a 'workaround' for this case would help if XAER_RMERR would be returned as it means that transaction should be rollbacked and the value of database is in state as it would be after rollback.