BTM

Getting details on Oracle XA Exception

Details

  • Type: New Feature New Feature
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: 2.0.1, 2.1.0
  • Fix Version/s: 2.1.3
  • Component/s: None
  • Labels:
    None
  • Environment:
    Oracle 10g2
  • Number of attachments :
    2

Description

When an Oracle XA exception occurs, it looks like we are getting too few details on the error to fix it.

That's true it can be seen as an issue in Oracle JDBC (XA) Driver, but the fact is we get only this:

Caused by: bitronix.tm.internal.BitronixSystemException: cannot enlist an XAResourceHolderState with uniqueName=CBKDBMS XAResource=oracle.jdbc.driver.T4CXAResource@111089b with XID a Bitronix XID [737072696E672D62746D0000012C34CB08600000012B : 737072696E672D62746D0000012C34CB08600000012D], error=XAER_RMERR
[...]
... 118 more
Caused by: oracle.jdbc.xa.OracleXAException
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1045)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:249)
at bitronix.tm.internal.XAResourceHolderState.start(XAResourceHolderState.java:192)
at bitronix.tm.internal.XAResourceManager.enlist(XAResourceManager.java:89)
at bitronix.tm.BitronixTransaction.enlistResource(BitronixTransaction.java:74)
... 120 more

Activity

Hide
Johann Dupuis added a comment -

Applying the next patch I get:

The XA Error is :-3
The XA Error message is :A resource manager error has occured in the transaction branch.
The Oracle Error code is :24784
The Oracle SQL Error code is :0
OracleXAException cause:

Show
Johann Dupuis added a comment - Applying the next patch I get: The XA Error is :-3 The XA Error message is :A resource manager error has occured in the transaction branch. The Oracle Error code is :24784 The Oracle SQL Error code is :0 OracleXAException cause:
Hide
Johann Dupuis added a comment -

Knowing that XA Exception was due to "ORA-24784: Transaction exists" has helped me to understand the problem (usage of database links with XA transaction is not "well" supported by Oracle).

Show
Johann Dupuis added a comment - Knowing that XA Exception was due to "ORA-24784: Transaction exists" has helped me to understand the problem (usage of database links with XA transaction is not "well" supported by Oracle).
Hide
Johann Dupuis added a comment - - edited

In "BitronixTransaction.java" (in "enlistResource(XAResource xaResource)" function) , I modify this:

try {
            resourceManager.enlist(resourceHolderState);
        } catch (XAException ex) {
        	if (ex instanceof oracle.jdbc.xa.OracleXAException){
        		oracle.jdbc.xa.OracleXAException oracleXAException= (oracle.jdbc.xa.OracleXAException)ex;
        		int xaError= oracleXAException.getXAError();
        		log.info("The XA Error is :" + xaError);
        		String xaErrorMsg= oracle.jdbc.xa.OracleXAException.getXAErrorMessage(xaError);
        		log.info("The XA Error message is :" + xaErrorMsg);
        		int oracleError= oracleXAException.getOracleError();
        		log.info("The Oracle Error code is :" + oracleError);
        		int oracleSQLError= oracleXAException.getOracleSQLError();
        		log.info("The Oracle SQL Error code is :" + oracleSQLError);
        		log.info("OracleXAException cause:", oracleXAException.getCause());
        	}
        	
            if (BitronixXAException.isUnilateralRollback(ex)) {
Show
Johann Dupuis added a comment - - edited In "BitronixTransaction.java" (in "enlistResource(XAResource xaResource)" function) , I modify this:
try {
            resourceManager.enlist(resourceHolderState);
        } catch (XAException ex) {
        	if (ex instanceof oracle.jdbc.xa.OracleXAException){
        		oracle.jdbc.xa.OracleXAException oracleXAException= (oracle.jdbc.xa.OracleXAException)ex;
        		int xaError= oracleXAException.getXAError();
        		log.info("The XA Error is :" + xaError);
        		String xaErrorMsg= oracle.jdbc.xa.OracleXAException.getXAErrorMessage(xaError);
        		log.info("The XA Error message is :" + xaErrorMsg);
        		int oracleError= oracleXAException.getOracleError();
        		log.info("The Oracle Error code is :" + oracleError);
        		int oracleSQLError= oracleXAException.getOracleSQLError();
        		log.info("The Oracle SQL Error code is :" + oracleSQLError);
        		log.info("OracleXAException cause:", oracleXAException.getCause());
        	}
        	
            if (BitronixXAException.isUnilateralRollback(ex)) {
Hide
Johann Dupuis added a comment -

This patch is definitively not clean at all.

I wonder if it is useful to add a mechanism to extract more from XAException (probably database dependent) or if it's an issue only for Oracle.

Show
Johann Dupuis added a comment - This patch is definitively not clean at all. I wonder if it is useful to add a mechanism to extract more from XAException (probably database dependent) or if it's an issue only for Oracle.
Hide
Ludovic Orban added a comment -

AFAIK Oracle is the only database out there with a JDBC driver completely unable to report useful error messages using the standard exception mechanism.

I've created custom BTM builds with this exact kind of code in the past to work around the problem but I've always been very reluctant to include that in the official code base as this problem has always been very specific to Oracle.

If you can come up with a clean patch that doesn't require any dependency on the Oracle JDBC driver and doesn't harm other databases and doesn't require me to do much work I will consider accepting it.

Show
Ludovic Orban added a comment - AFAIK Oracle is the only database out there with a JDBC driver completely unable to report useful error messages using the standard exception mechanism. I've created custom BTM builds with this exact kind of code in the past to work around the problem but I've always been very reluctant to include that in the official code base as this problem has always been very specific to Oracle. If you can come up with a clean patch that doesn't require any dependency on the Oracle JDBC driver and doesn't harm other databases and doesn't require me to do much work I will consider accepting it.
Hide
Ludovic Orban added a comment -

Implemented a generic mechanism which allows extracting that kind of information from a vendor's XAException and the default implementation reports the ORA-xyz error code from Oracle's XAException.

Show
Ludovic Orban added a comment - Implemented a generic mechanism which allows extracting that kind of information from a vendor's XAException and the default implementation reports the ORA-xyz error code from Oracle's XAException.
Hide
Ludovic Orban added a comment -

I deployed a 2.1.3-SNAPSHOT version in the codehaus snapshot repository.

Could you please try it out and report back here if it works as you expected? See http://docs.codehaus.org/display/BTM/Maven2#Maven2-Earlyversions for the details about how to configure your Maven 2 pom to get access to the BTM snapshots.

Thanks!

Show
Ludovic Orban added a comment - I deployed a 2.1.3-SNAPSHOT version in the codehaus snapshot repository. Could you please try it out and report back here if it works as you expected? See http://docs.codehaus.org/display/BTM/Maven2#Maven2-Earlyversions for the details about how to configure your Maven 2 pom to get access to the BTM snapshots. Thanks!
Hide
Johann Dupuis added a comment -

It works as expected, we can know get more information about the XAException to workaround Oracle poor implementation.

I have tested the ability to specify in configuration a custom implementation for the ExceptionAnalyzer.
Find attached my own implementation, still focused on Oracle but with few more details.

But, analysing more the source code, I think it could worth to extend the mechanism to every location of XAException handling:
"BitronixTransaction#enlistResource" is not the only place where we can get meaningless Oracle XA Exception, but
"BitronixTransaction#delistResourse",
"Recoverer#recoverAllResources",
"BitronixTransactionManager#suspend",
"BitronixMultiSystemException#getMessage",
"RecoveryHelper#commit",
"RecoveryHelper#rollback",
"PhaseException#...",
"Committer#..." ...

We might extend "bitronix.tm.utils.Decoder" to override function "decodeXAExceptionErrorCode" or simply add a function "decodeXAExceptionErrorCodeWithExtraDetails".

Show
Johann Dupuis added a comment - It works as expected, we can know get more information about the XAException to workaround Oracle poor implementation. I have tested the ability to specify in configuration a custom implementation for the ExceptionAnalyzer. Find attached my own implementation, still focused on Oracle but with few more details. But, analysing more the source code, I think it could worth to extend the mechanism to every location of XAException handling: "BitronixTransaction#enlistResource" is not the only place where we can get meaningless Oracle XA Exception, but "BitronixTransaction#delistResourse", "Recoverer#recoverAllResources", "BitronixTransactionManager#suspend", "BitronixMultiSystemException#getMessage", "RecoveryHelper#commit", "RecoveryHelper#rollback", "PhaseException#...", "Committer#..." ... We might extend "bitronix.tm.utils.Decoder" to override function "decodeXAExceptionErrorCode" or simply add a function "decodeXAExceptionErrorCodeWithExtraDetails".
Hide
Johann Dupuis added a comment -

Custom implementation of ExceptionAnalyzer (for Oracle with all details).

Show
Johann Dupuis added a comment - Custom implementation of ExceptionAnalyzer (for Oracle with all details).
Hide
Johann Dupuis added a comment -

Is it possible to extend the mechanism to every location of XAException handling?

Show
Johann Dupuis added a comment - Is it possible to extend the mechanism to every location of XAException handling?
Hide
Ludovic Orban added a comment -

Yes, this will be done.

Show
Ludovic Orban added a comment - Yes, this will be done.
Hide
Ludovic Orban added a comment -

I've just pushed the changes that make this mechanism present at all places where XAException is handled and published a new 2.1.3-SNAPSHOT version in codehaus' snapshots repo.

Could you please have a look at it and let me know if this works up to your expecations? As a reminder, the instructions to access codehaus' snapshots repo is at http://docs.codehaus.org/display/BTM/Maven2#Maven2-Earlyversions

Show
Ludovic Orban added a comment - I've just pushed the changes that make this mechanism present at all places where XAException is handled and published a new 2.1.3-SNAPSHOT version in codehaus' snapshots repo. Could you please have a look at it and let me know if this works up to your expecations? As a reminder, the instructions to access codehaus' snapshots repo is at http://docs.codehaus.org/display/BTM/Maven2#Maven2-Earlyversions
Hide
Johann Dupuis added a comment -

I will have a look before the end of next week. Sorry for the delay.

Show
Johann Dupuis added a comment - I will have a look before the end of next week. Sorry for the delay.
Hide
Johann Dupuis added a comment -

The snapshot from 27 Feb 2012 looks fine to me, except:

  • in rollbacker.java, around line 199, there is a call to "Decoder.decodeXAExceptionErrorCode(xaException)" but we aren't handling 'extractExtraXAExceptionDetails'
  • in TransactionManagerServices.java, in function "getExceptionAnalyzer()", if the 'ClassLoaderUtils.loadClass' fails (due to mistake in exceptionAnalyzerName, packaging issue, ...) we are throwing a new InitializationException that would hide XAException or at least modify the handling of XAException in the caller method.
    Please find attached a proposal that adds a detailed error message in the log when 'ClassLoaderUtils.loadClass' fails but return the DefaultExceptionAnalyzer that would have no impact on caller method.
    To check that behaviour, I have:
    • Modified the Oracle JDBC Driver to return an Oracle XAException (instead of a javax.transaction.xa.XAException) in case privileges are missing
    • Start my application with no custom exception analyzer -> application fail to start because of missing privileges --> OK
    • Start my application with mispelled custom exception analyzer name -> InitializationException thrown -> the application is starting --> NOK
    • Apply patch to TransactionManagerServices#getExceptionAnalyzer, then start my application with mispelled custom exception analyzer name -> InitializationException in log BUT DefaultExceptionAnalyzer is used -> the application fail to start because of missing privileges --> OK
Show
Johann Dupuis added a comment - The snapshot from 27 Feb 2012 looks fine to me, except:
  • in rollbacker.java, around line 199, there is a call to "Decoder.decodeXAExceptionErrorCode(xaException)" but we aren't handling 'extractExtraXAExceptionDetails'
  • in TransactionManagerServices.java, in function "getExceptionAnalyzer()", if the 'ClassLoaderUtils.loadClass' fails (due to mistake in exceptionAnalyzerName, packaging issue, ...) we are throwing a new InitializationException that would hide XAException or at least modify the handling of XAException in the caller method. Please find attached a proposal that adds a detailed error message in the log when 'ClassLoaderUtils.loadClass' fails but return the DefaultExceptionAnalyzer that would have no impact on caller method. To check that behaviour, I have:
    • Modified the Oracle JDBC Driver to return an Oracle XAException (instead of a javax.transaction.xa.XAException) in case privileges are missing
    • Start my application with no custom exception analyzer -> application fail to start because of missing privileges --> OK
    • Start my application with mispelled custom exception analyzer name -> InitializationException thrown -> the application is starting --> NOK
    • Apply patch to TransactionManagerServices#getExceptionAnalyzer, then start my application with mispelled custom exception analyzer name -> InitializationException in log BUT DefaultExceptionAnalyzer is used -> the application fail to start because of missing privileges --> OK
Hide
Johann Dupuis added a comment -

See 'getExceptionAnalyzer' function

Show
Johann Dupuis added a comment - See 'getExceptionAnalyzer' function
Hide
Ludovic Orban added a comment -

Latest suggestions have been incorporated into the 2.1.x branch.

Thanks for you help on this issue!

Show
Ludovic Orban added a comment - Latest suggestions have been incorporated into the 2.1.x branch. Thanks for you help on this issue!

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: