BTM
  1. BTM
  2. BTM-98

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
    • 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

      1. OracleExceptionAnalyzer.java
        2 kB
        Johann Dupuis
      2. TransactionManagerServices.java
        10 kB
        Johann Dupuis

        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

          • Assignee:
            Ludovic Orban
            Reporter:
            Johann Dupuis
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: