Uploaded image for project: 'Derby'
  1. Derby
  2. DERBY-4232

XAResource.setTransactionTimeout() makes XAResource.start() fail with the client driver

    XMLWordPrintableJSON

    Details

    • Bug behavior facts:
      Regression

      Description

      Got below error message when running an XA prolgram with derby.
      org.apache.derby.client.am.XaException: XAER_PROTO : Error executing a XAResource.start(), server returned XAER_PROTO.
      at org.apache.derby.client.net.NetXAResource.throwXAException(Unknown Source)
      at org.apache.derby.client.net.NetXAResource.start(Unknown Source)
      at TestDerbyXA.process(TestDerbyXA.java:186)
      at TestDerbyXA.main(TestDerbyXA.java:43)
      Caused by: org.apache.derby.client.am.SqlException: Error executing a XAResource.start(), server returned XAER_PROTO.
      at org.apache.derby.client.net.NetXAResource.xaRetValErrorAccumSQL(Unknown Source)
      ... 3 more

      Below is the example program I used. Note: The program will succeed if comment out line 147 - setTransactionTimeout. Does that means call XAResource.setTransactionTimeout() caused the failure?
      I use Apache Derby Network Server - 10.4.2.0 - (689064). The same program works fine with another version Apache Derby Network Server - 10.2.2.0 - (485682). It looks like there is a regression between the two versions.

      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.SQLException;
      import java.sql.Statement;

      import javax.sql.XAConnection;
      import javax.transaction.xa.XAException;
      import javax.transaction.xa.XAResource;
      import javax.transaction.xa.Xid;

      import org.apache.derby.jdbc.ClientXADataSource;

      public class TestDerbyXA {

      ClientXADataSource xaDSLocal = null;

      ClientXADataSource xaDSRemote = null;

      public TestDerbyXA()

      { // Create two XA data sources. xaDSLocal = new ClientXADataSource(); xaDSLocal.setServerName("localhost"); xaDSLocal.setPortNumber(1527); xaDSLocal.setDatabaseName("testdb"); xaDSLocal.setUser("app"); xaDSLocal.setPassword("derby"); xaDSRemote = new ClientXADataSource(); xaDSRemote.setServerName("localhost"); xaDSRemote.setPortNumber(1527); xaDSRemote.setDatabaseName("testdb"); xaDSRemote.setUser("app"); xaDSRemote.setPassword("derby"); // xaDSRemote = xaDSLocal; }

      public static void main(String[] args) throws Exception

      { TestDerbyXA testObj = new TestDerbyXA(); testObj.dropTable("tablea"); testObj.createTable("CREATE TABLE tablea (col1 INT, col2 VARCHAR(32))"); testObj.dropTable("tableb"); testObj.createTable("CREATE TABLE tableb (col1 INT, col2 VARCHAR(32))"); testObj.process(); }

      public void dropTable(String tableName) throws Exception {
      Connection conn = null;
      Statement stmt = null;

      try

      { conn = xaDSLocal.getConnection(); stmt = conn.createStatement(); stmt.executeUpdate("DROP TABLE " + tableName); System.out.println("Drop table " + tableName + " succeed."); }

      catch (SQLException sqle)

      { System.out.println("Drop table " + tableName + " failed."); sqle.printStackTrace(); }

      finally {
      // ============ Close JDBC objects, including the connection =======
      if (stmt != null) {
      try

      { stmt.close(); stmt = null; } catch (SQLException e) {
      }
      }
      if (conn != null) {
      try { conn.close(); conn = null; } catch (SQLException e) {
      }
      }
      }
      }

      public void createTable(String DDL) throws Exception {
      Connection conn = null;
      Statement stmt = null;

      try { conn = xaDSLocal.getConnection(); stmt = conn.createStatement(); stmt.executeUpdate(DDL); System.out.println(DDL + " succeed."); } catch (SQLException sqle) { System.out.println(DDL + " failed."); sqle.printStackTrace(); } finally {
      // ============ Close JDBC objects, including the connection =======
      if (stmt != null) {
      try { stmt.close(); stmt = null; }

      catch (SQLException e) {
      }
      }
      if (conn != null) {
      try

      { conn.close(); conn = null; }

      catch (SQLException e) {
      }
      }
      }
      }

      public void process() throws Exception {
      Connection connLocal = null;
      Connection connRemote = null;
      int rows = 0;
      PreparedStatement pstmtLocal = null;
      PreparedStatement pstmtRemote = null;
      XAConnection xaConnLocal = null;
      XAConnection xaConnRemote = null;
      XAResource xarLocal = null;
      XAResource xarRemote = null;
      Xid xidLocal = null;
      Xid xidRemote = null;
      try

      { xaConnLocal = xaDSLocal.getXAConnection(); xaConnRemote = xaDSRemote.getXAConnection(); connLocal = xaConnLocal.getConnection(); connRemote = xaConnRemote.getConnection(); xarLocal = xaConnLocal.getXAResource(); xarRemote = xaConnRemote.getXAResource(); // Create the Xids // Create the global ID byte[] globalTransactionId1 = new byte[64]; globalTransactionId1[0] = (byte) 1; byte[] globalTransactionId2 = new byte[64]; globalTransactionId2[0] = (byte) 2; // Create the local branch ID byte[] branchQualifierLocal = new byte[64]; branchQualifierLocal[0] = (byte) 1; xidLocal = new XidImpl(globalTransactionId1, branchQualifierLocal, 0x1234); // Create the remote branch ID byte[] branchQualifierRemote = new byte[64]; branchQualifierRemote[0] = (byte) 2; xidRemote = new XidImpl(globalTransactionId2, branchQualifierRemote, 0x1234); // Database operations on the local branch, suspend local branch xarLocal.setTransactionTimeout(500); //!!! The failure will disappear if comment out this line. connLocal.setAutoCommit(false); xarLocal.start(xidLocal, XAResource.TMNOFLAGS); pstmtLocal = connLocal .prepareStatement("INSERT INTO tablea (col1, col2) VALUES (?, ?)"); pstmtLocal.setInt(1, 1); pstmtLocal.setString(2, "insert first rec to tablea"); rows = pstmtLocal.executeUpdate(); System.out.println(rows + " rows inserted to tablea"); pstmtLocal.close(); pstmtLocal = null; xarLocal.end(xidLocal, XAResource.TMSUCCESS); connLocal.setAutoCommit(true); // Database operation on the remote branch, commit remote branch xarRemote.setTransactionTimeout(500); connRemote.setAutoCommit(false); xarRemote.start(xidRemote, XAResource.TMNOFLAGS); pstmtRemote = connRemote .prepareStatement("INSERT INTO tableb (col1, col2) VALUES (?, ?)"); pstmtRemote.setInt(1, 2); pstmtRemote.setString(2, "insert second rec to tableb"); rows = pstmtRemote.executeUpdate(); System.out.println(rows + " rows inserted to tableb"); pstmtRemote.close(); pstmtRemote = null; xarRemote.end(xidRemote, XAResource.TMSUCCESS); connRemote.setAutoCommit(true); System.out.println("commit remote branch"); xarRemote.commit(xidRemote, true); // Resume the local branch and do some database operation, commit local branch xarLocal.setTransactionTimeout(500); connLocal.setAutoCommit(false); xarLocal.start(xidLocal, XAResource.TMJOIN); pstmtLocal = connLocal .prepareStatement("INSERT INTO tablea (col1, col2) VALUES (?, ?)"); pstmtLocal.setInt(1, 3); pstmtLocal.setString(2, "insert third rec to tablea"); rows = pstmtLocal.executeUpdate(); System.out.println(rows + " rows inserted to tablea"); pstmtLocal.close(); pstmtLocal = null; xarLocal.end(xidLocal, XAResource.TMSUCCESS); connLocal.setAutoCommit(true); System.out.println("commit local branch"); xarLocal.commit(xidLocal, true); // Close the resources connLocal.close(); connLocal = null; connRemote.close(); connRemote = null; xaConnLocal.close(); xaConnLocal = null; xaConnRemote.close(); xaConnRemote = null; }

      catch (SQLException e)

      { System.err.println("SQL Error: " + e.getMessage()); e.printStackTrace(); }

      catch (XAException e)

      { System.err.println("XA Error: " + e.getMessage()); e.printStackTrace(); }

      finally {
      if (pstmtLocal != null)
      try

      { pstmtLocal.close(); pstmtLocal = null; }

      catch (SQLException ignore) {
      }
      if (pstmtRemote != null)
      try

      { pstmtRemote.close(); pstmtRemote = null; }

      catch (SQLException ignore) {
      }
      if (connLocal != null)
      try

      { connLocal.close(); connLocal = null; }

      catch (SQLException ignore) {
      }
      if (connRemote != null)
      try

      { connRemote.close(); connRemote = null; }

      catch (SQLException ignore) {
      }
      if (xaConnLocal != null)
      try

      { xaConnLocal.close(); xaConnLocal = null; }

      catch (SQLException ignore) {
      }
      if (xaConnRemote != null)
      try

      { xaConnRemote.close(); xaConnRemote = null; }

      catch (SQLException ignore) {
      }
      }
      }
      }

        Attachments

        1. test.diff
          3 kB
          Knut Anders Hatlen
        2. d4232-1a.diff
          0.8 kB
          Knut Anders Hatlen

          Activity

            People

            • Assignee:
              knutanders Knut Anders Hatlen
              Reporter:
              simon.meng Simon Meng
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: