public void testDelistErrorAndUnilateralRollbackOnCommit() throws Exception {
    btm.begin();

    Connection connection1 = poolingDataSource1.getConnection();
    JdbcConnectionHandle handle1 = (JdbcConnectionHandle) Proxy.getInvocationHandler(connection1);
    XAConnection xaConnection1 =
        (XAConnection) AbstractMockJdbcTest.getWrappedXAConnectionOf(handle1.getPooledConnection());
    MockXAResource xaResource1 = (MockXAResource) xaConnection1.getXAResource();
    xaResource1.setEndException(
        new BitronixXAException("screw delistment", XAException.XAER_RMERR));
    xaResource1.setRollbackException(
        new BitronixXAException("delistment was screwed, cannot rollback", XAException.XAER_RMERR));

    connection1.createStatement(); // triggers enlistment

    Connection connection2 = poolingDataSource2.getConnection();
    JdbcConnectionHandle handle2 = (JdbcConnectionHandle) Proxy.getInvocationHandler(connection2);
    XAConnection xaConnection2 =
        (XAConnection) AbstractMockJdbcTest.getWrappedXAConnectionOf(handle2.getPooledConnection());
    MockXAResource xaResource2 = (MockXAResource) xaConnection2.getXAResource();
    xaResource2.setEndException(
        new BitronixXAException("what was that transaction again?", XAException.XAER_NOTA));
    xaResource2.setRollbackException(
        new BitronixXAException(
            "delistment unilaterally rolled back, cannot rollback twice", XAException.XAER_RMERR));

    connection2.createStatement(); // triggers enlistment

    try {
      btm.commit();
      fail("expected RollbackException");
    } catch (RollbackException ex) {
      assertEquals(
          "delistment error caused transaction rollback"
              + System.getProperty("line.separator")
              + "  resource(s) [pds2] unilaterally rolled back"
              + System.getProperty("line.separator")
              + "  resource(s) [pds1] could not be delisted",
          ex.getMessage());
    }

    // check flow
    List orderedEvents = EventRecorder.getOrderedEvents();
    log.info(EventRecorder.dumpToString());

    assertEquals(8, orderedEvents.size());
    int i = 0;
    assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
    assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
    assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
    assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
    assertEquals(
        Status.STATUS_MARKED_ROLLBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
    assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
    assertEquals(
        Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
    assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
  }
  //
  // Find all the objects inside the XADataSource and vet them.
  //
  private void vetXADataSource(HashSet<String> unsupportedList, HashSet<String> notUnderstoodList)
      throws Exception {
    XADataSource ds = J2EEDataSource.getXADataSource();
    XAConnection xaconn =
        ds.getXAConnection(
            getTestConfiguration().getUserName(), getTestConfiguration().getUserPassword());
    Connection conn = xaconn.getConnection();

    vetObject(ds, unsupportedList, notUnderstoodList);
    vetObject(xaconn, unsupportedList, notUnderstoodList);

    connectionWorkhorse(conn, unsupportedList, notUnderstoodList);
  }
 protected void setUp() throws Exception {
   include(PATH);
   xads2_ = (XADataSource) getComponent("xads");
   xacon_ = xads2_.getXAConnection();
   con_ = xacon_.getConnection();
   xares_ = new DBXAResourceImpl(con_);
 }
 protected int doCommit(Xid xid, int cPhase) throws XAException {
   int returnVal = -1;
   synchronized (physicalConn) {
     synchronized (this) {
       int command = cPhase != 1 ? 2 : 4;
       returnVal = doTransaction(xid, 1, command);
       if (cPhase == 1 && (returnVal == 2 || returnVal == 4)) {
         returnVal = 0;
       } else if (cPhase != 1 && returnVal == 5) {
         returnVal = 0;
       } else if (returnVal == 8) {
         throw new XAException(106);
       }
       if (returnVal == 24756) {
         returnVal = kputxrec(xid, 1, timeout + 120);
       } else if (returnVal == 24780) {
         OracleXADataSource oxds = null;
         XAConnection pc = null;
         try {
           oxds = new OracleXADataSource();
           oxds.setURL(physicalConn.url);
           oxds.setUser(physicalConn.user);
           physicalConn.getPasswordInternal(this);
           oxds.setPassword(password);
           pc = oxds.getXAConnection();
           XAResource oxar = pc.getXAResource();
           oxar.commit(xid, cPhase == 1);
           returnVal = 0;
         } catch (SQLException e) {
           throw new XAException(-6);
         } finally {
           try {
             if (pc != null) {
               pc.close();
             }
             if (oxds != null) {
               oxds.close();
             }
           } catch (Exception ee) {
           }
         }
       }
     }
   }
   return returnVal;
 }
 protected int doRollback(Xid xid) throws XAException {
   int returnVal = -1;
   synchronized (physicalConn) {
     synchronized (this) {
       returnVal = doTransaction(xid, 2, 3);
       if (returnVal == 8) {
         throw new XAException(106);
       }
       if (returnVal == 3 || returnVal == 25402) {
         returnVal = 0;
       }
       if (returnVal == 24756) {
         returnVal = kputxrec(xid, 2, timeout + 120);
       } else if (returnVal == 24780) {
         OracleXADataSource oxds = null;
         XAConnection pc = null;
         try {
           oxds = new OracleXADataSource();
           oxds.setURL(physicalConn.url);
           oxds.setUser(physicalConn.user);
           physicalConn.getPasswordInternal(this);
           oxds.setPassword(password);
           pc = oxds.getXAConnection();
           XAResource oxar = pc.getXAResource();
           oxar.rollback(xid);
           returnVal = 0;
         } catch (SQLException e) {
           throw new XAException(-6);
         } finally {
           try {
             if (pc != null) {
               pc.close();
             }
             if (oxds != null) {
               oxds.close();
             }
           } catch (Exception ee) {
           }
         }
       }
     }
   }
   return returnVal;
 }
  @Override
  public Connection createConnection() throws SQLException {
    // create a new XAConection
    XAConnection xaConnection;
    if (username == null) {
      xaConnection = xaDataSource.getXAConnection();
    } else {
      xaConnection = xaDataSource.getXAConnection(username, password);
    }

    // get the real connection and XAResource from the connection
    Connection connection = xaConnection.getConnection();
    XAResource xaResource = xaConnection.getXAResource();

    // register the xa resource for the connection
    transactionRegistry.registerConnection(connection, xaResource);

    // PATCH: register a ConnectionEventListener for close
    // See DBCP-355
    // The Connection we're returning is a handle on the XAConnection.
    // When the pool calling us closes the Connection, we need to
    // also close the XAConnection that holds the physical connection.
    xaConnection.addConnectionEventListener(
        new ConnectionEventListener() {
          @Override
          public void connectionClosed(ConnectionEvent event) {
            PooledConnection pc = (PooledConnection) event.getSource();
            pc.removeConnectionEventListener(this);
            try {
              pc.close();
            } catch (SQLException e) {
              log.error("Failed to close XAConnection", e);
            }
          }

          @Override
          public void connectionErrorOccurred(ConnectionEvent event) {
            connectionClosed(event);
          }
        });

    return connection;
  }
 /**
  * Test XA Connection for chinese database name, user and password.
  *
  * @throws SQLException
  */
 public void testXADSConnect() throws SQLException {
   // Test chinese database name.
   XADataSource ds = J2EEDataSource.getXADataSource();
   J2EEDataSource.setBeanProperty(ds, "databaseName", "\u4e10");
   J2EEDataSource.setBeanProperty(ds, "createDatabase", "create");
   try {
     XAConnection xaconn = ds.getXAConnection();
     Connection conn = xaconn.getConnection();
     conn.close();
   } catch (SQLException se) {
     if (usingEmbedded()) throw se;
     else assertSQLState("22005", se);
   }
   // Chinese user
   try {
     J2EEDataSource.setBeanProperty(ds, "user", "\u4e10");
     XAConnection xaconn = ds.getXAConnection();
     Connection conn = xaconn.getConnection();
     conn.close();
   } catch (SQLException se) {
     if (usingEmbedded()) throw se;
     else assertSQLState("22005", se);
   }
   // Chinese password
   try {
     J2EEDataSource.setBeanProperty(ds, "password", "\u4e10");
     XAConnection xaconn = ds.getXAConnection();
     Connection conn = xaconn.getConnection();
     conn.close();
   } catch (SQLException se) {
     if (usingEmbedded()) throw se;
     else assertSQLState("22005", se);
   }
 }
  public ManagedConnection getXAManagedConnection(Subject subject, ConnectionRequestInfo cri)
      throws javax.resource.ResourceException {
    XAConnection xaConnection = null;
    Properties props = getConnectionProperties(subject, cri);
    try {
      final String user = props.getProperty("user");
      final String password = props.getProperty("password");

      xaConnection =
          (user != null)
              ? getXADataSource().getXAConnection(user, password)
              : getXADataSource().getXAConnection();

      return newXAManagedConnection(props, xaConnection);
    } catch (Throwable e) {
      try {
        if (xaConnection != null) xaConnection.close();
      } catch (Throwable ignored) {
      }
      throw new JBossResourceException("Could not create connection", e);
    }
  }
Beispiel #9
0
  private void checkXAHoldability() {
    System.out.println("START XA HOLDABILITY TEST");
    try {
      EmbeddedXADataSource dscsx = new EmbeddedXADataSource();
      dscsx.setDatabaseName("wombat");

      XAConnection xac = dscsx.getXAConnection("fred", "wilma");
      XAResource xr = xac.getXAResource();
      Xid xid = getXid(25, (byte) 21, (byte) 01);
      Connection conn1 = xac.getConnection();
      System.out.println(
          "By default, autocommit is " + conn1.getAutoCommit() + " for a connection");
      System.out.println("Default holdability for a connection is HOLD_CURSORS_OVER_COMMIT");
      System.out.println(
          "CONNECTION(not in xa transaction yet) HOLDABILITY "
              + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      // start a global transaction and default holdability and autocommit will be switched to match
      // Derby XA restrictions
      xr.start(xid, XAResource.TMNOFLAGS);
      System.out.println(
          "Notice that autocommit now is "
              + conn1.getAutoCommit()
              + " for connection because it is part of the global transaction");
      System.out.println(
          "Notice that connection's holdability at this point is CLOSE_CURSORS_AT_COMMIT because it is part of the global transaction");
      System.out.println(
          "CONNECTION(in xa transaction) HOLDABILITY "
              + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      xr.end(xid, XAResource.TMSUCCESS);
      conn1.commit();
      conn1.close();

      xid = getXid(27, (byte) 21, (byte) 01);
      xr.start(xid, XAResource.TMNOFLAGS);
      conn1 = xac.getConnection();
      System.out.println(
          "CONNECTION(in xa transaction) HOLDABILITY "
              + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "Autocommit on Connection inside global transaction has been set correctly to "
              + conn1.getAutoCommit());
      xr.end(xid, XAResource.TMSUCCESS);
      conn1.rollback();

      Connection conn = xac.getConnection();
      conn.setAutoCommit(false);
      conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
      System.out.println(
          "CONNECTION(non-xa) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      Statement s = conn.createStatement();
      System.out.println(
          "STATEMENT HOLDABILITY "
              + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      s.executeUpdate("create table hold_30 (id int not null primary key, b char(30))");
      s.executeUpdate("insert into hold_30 values (1,'init2'), (2, 'init3'), (3,'init3')");
      s.executeUpdate("insert into hold_30 values (4,'init4'), (5, 'init5'), (6,'init6')");
      s.executeUpdate("insert into hold_30 values (7,'init7'), (8, 'init8'), (9,'init9')");

      System.out.println(
          "STATEMENT HOLDABILITY "
              + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      Statement sh =
          conn.createStatement(
              ResultSet.TYPE_FORWARD_ONLY,
              ResultSet.CONCUR_READ_ONLY,
              ResultSet.HOLD_CURSORS_OVER_COMMIT);
      PreparedStatement psh =
          conn.prepareStatement(
              "select id from hold_30 for update",
              ResultSet.TYPE_FORWARD_ONLY,
              ResultSet.CONCUR_READ_ONLY,
              ResultSet.HOLD_CURSORS_OVER_COMMIT);
      CallableStatement csh =
          conn.prepareCall(
              "select id from hold_30 for update",
              ResultSet.TYPE_FORWARD_ONLY,
              ResultSet.CONCUR_READ_ONLY,
              ResultSet.HOLD_CURSORS_OVER_COMMIT);

      System.out.println(
          "STATEMENT HOLDABILITY "
              + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "PREPARED STATEMENT HOLDABILITY "
              + (psh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "CALLABLE STATEMENT HOLDABILITY "
              + (csh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      ResultSet rsh = sh.executeQuery("select id from hold_30 for update");
      rsh.next();
      System.out.println("H@1 id " + rsh.getInt(1));
      rsh.next();
      System.out.println("H@2 id " + rsh.getInt(1));
      conn.commit();
      rsh.next();
      System.out.println("H@3 id " + rsh.getInt(1));
      conn.commit();

      xid = getXid(23, (byte) 21, (byte) 01);
      xr.start(xid, XAResource.TMNOFLAGS);
      Statement stmtInsideGlobalTransaction = conn.createStatement();
      PreparedStatement prepstmtInsideGlobalTransaction =
          conn.prepareStatement("select id from hold_30");
      CallableStatement callablestmtInsideGlobalTransaction =
          conn.prepareCall("select id from hold_30");

      System.out.println(
          "CONNECTION(xa) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with holdability false, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY "
              + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with holdability true, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY "
              + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY "
              + (stmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "PREPAREDSTATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY "
              + (prepstmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "CALLABLESTATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY "
              + (callablestmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      ResultSet rsx = s.executeQuery("select id from hold_30 for update");
      rsx.next();
      System.out.println("X@1 id " + rsx.getInt(1));
      rsx.next();
      System.out.println("X@2 id " + rsx.getInt(1));
      xr.end(xid, XAResource.TMSUCCESS);

      // result set should not be useable, since it is part of a detached
      // XAConnection
      try {
        rsx.next();
        System.out.println("FAIL - rsx's connection not active id " + rsx.getInt(1));
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException " + sqle.getMessage());
      }

      // result set should not be useable, it should have been closed by the xa start.
      try {
        rsh.next();
        System.out.println("FAIL - rsh's should be closed " + rsx.getInt(1));
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException " + sqle.getMessage());
      }

      System.out.println("resume XA transaction and keep using rs");
      xr.start(xid, XAResource.TMJOIN);
      Statement stmtAfterGlobalTransactionResume = conn.createStatement();
      PreparedStatement prepstmtAfterGlobalTransactionResume =
          conn.prepareStatement("select id from hold_30");
      CallableStatement callablestmtAfterGlobalTransactionResume =
          conn.prepareCall("select id from hold_30");

      System.out.println("Check holdability of various jdbc objects after resuming XA transaction");
      System.out.println(
          "CONNECTION(xa) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with holdability false, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY "
              + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with holdability true, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY "
              + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY "
              + (stmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "PREPAREDSTATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY "
              + (prepstmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "CALLABLESTATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY "
              + (callablestmtInsideGlobalTransaction.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "STATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY "
              + (stmtAfterGlobalTransactionResume.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "PREPAREDSTATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY "
              + (prepstmtAfterGlobalTransactionResume.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      System.out.println(
          "CALLABLESTATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY "
              + (callablestmtAfterGlobalTransactionResume.getResultSetHoldability()
                  == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      rsx.next();
      System.out.println("X@3 id " + rsx.getInt(1));
      xr.end(xid, XAResource.TMSUCCESS);

      if (xr.prepare(xid) != XAResource.XA_RDONLY) xr.commit(xid, false);

      // try again once the xa transaction has been committed.
      try {
        rsx.next();
        System.out.println("FAIL - rsx's connection not active id (B)" + rsx.getInt(1));
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException " + sqle.getMessage());
      }

      try {
        rsh.next();
        System.out.println("FAIL - rsh's should be closed (B) " + rsx.getInt(1));
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException " + sqle.getMessage());
      }

      System.out.println("Set connection to hold ");
      conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
      System.out.println(
          "CONNECTION(held) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      xid = getXid(24, (byte) 21, (byte) 01);
      xr.start(xid, XAResource.TMNOFLAGS);
      System.out.println(
          "CONNECTION(xa) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      try {
        conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
        System.out.println("FAIL allowed to set hold mode in xa transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException(setHoldability) " + sqle.getMessage());
      }

      // try to create a statement with held attributes
      try {
        Statement shxa =
            conn.createStatement(
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY,
                ResultSet.HOLD_CURSORS_OVER_COMMIT);
        System.out.println(
            "FAIL opened statement with hold cursor attribute in global transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException (Statement hold) " + sqle.getMessage());
      }
      try {
        Statement shxa =
            conn.prepareStatement(
                "select id from hold_30",
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY,
                ResultSet.HOLD_CURSORS_OVER_COMMIT);
        System.out.println(
            "FAIL opened statement with hold cursor attribute in global transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException (PreparedStatement hold) " + sqle.getMessage());
      }
      try {
        Statement shxa =
            conn.prepareCall(
                "CALL XXX.TTT()",
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY,
                ResultSet.HOLD_CURSORS_OVER_COMMIT);
        System.out.println(
            "FAIL opened statement with hold cursor attribute in global transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException (CallableStatement hold) " + sqle.getMessage());
      }

      // check we cannot use a holdable statement set up in local mode.
      System.out.println(
          "STATEMENT HOLDABILITY "
              + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      try {
        sh.executeQuery("select id from hold_30");
        System.out.println("FAIL used held statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException (local Statement hold) " + sqle.getMessage());
      }
      try {
        sh.execute("select id from hold_30");
        System.out.println("FAIL used held statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println("Expected SQLException (local Statement hold) " + sqle.getMessage());
      }
      System.out.println(
          "PREPARED STATEMENT HOLDABILITY "
              + (psh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      try {
        psh.executeQuery();
        System.out.println("FAIL used held prepared statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println(
            "Expected SQLException (local PreparedStatement hold) " + sqle.getMessage());
      }
      try {
        psh.execute();
        System.out.println("FAIL used held prepared statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println(
            "Expected SQLException (local PreparedStatement hold) " + sqle.getMessage());
      }

      System.out.println(
          "CALLABLE STATEMENT HOLDABILITY "
              + (csh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));
      try {
        csh.executeQuery();
        System.out.println("FAIL used held callable statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println(
            "Expected SQLException (local CallableStatement hold) " + sqle.getMessage());
      }
      try {
        csh.execute();
        System.out.println("FAIL used held callable statement in global transaction");
      } catch (SQLException sqle) {
        System.out.println(
            "Expected SQLException (local CallableStatement hold) " + sqle.getMessage());
      }

      // but an update works
      sh.executeUpdate("insert into hold_30 values(10, 'init10')");

      xr.end(xid, XAResource.TMSUCCESS);

      System.out.println(
          "CONNECTION(held) HOLDABILITY "
              + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT));

      conn.close();
      System.out.println("PASS XA HOLDABILITY TEST");

    } catch (XAException xae) {
      System.out.println("XAException error code " + xae.errorCode);
      xae.printStackTrace(System.out);
      Throwable t = xae.getCause();
      if (t instanceof SQLException) JDBCDisplayUtil.ShowSQLException(System.out, (SQLException) t);

    } catch (SQLException sqle) {
      JDBCDisplayUtil.ShowSQLException(System.out, sqle);
    } catch (Throwable t) {
      t.printStackTrace(System.out);
    }
    System.out.flush();
  }
Beispiel #10
0
  /**
   * Tests that simple distributed transaction processing works as expected.
   *
   * @throws Exception if the test fails.
   */
  public void testCoordination() throws Exception {
    if (!versionMeetsMinimum(5, 0)) {
      return;
    }

    createTable("testCoordination", "(field1 int) ENGINE=InnoDB");

    Connection conn1 = null;
    Connection conn2 = null;
    XAConnection xaConn1 = null;
    XAConnection xaConn2 = null;

    try {
      xaConn1 = getXAConnection();
      XAResource xaRes1 = xaConn1.getXAResource();
      conn1 = xaConn1.getConnection();

      xaConn2 = getXAConnection();
      XAResource xaRes2 = xaConn2.getXAResource();
      conn2 = xaConn2.getConnection();

      Xid xid1 = createXid();
      Xid xid2 = createXid(xid1);

      xaRes1.start(xid1, XAResource.TMNOFLAGS);
      xaRes2.start(xid2, XAResource.TMNOFLAGS);
      conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)");
      conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");
      xaRes1.end(xid1, XAResource.TMSUCCESS);
      xaRes2.end(xid2, XAResource.TMSUCCESS);

      xaRes1.prepare(xid1);
      xaRes2.prepare(xid2);

      xaRes1.commit(xid1, false);
      xaRes2.commit(xid2, false);

      this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1");

      assertTrue(this.rs.next());
      assertEquals(1, this.rs.getInt(1));

      assertTrue(this.rs.next());
      assertEquals(2, this.rs.getInt(1));

      this.stmt.executeUpdate("TRUNCATE TABLE testCoordination");

      //
      // Now test rollback
      //

      xid1 = createXid();
      xid2 = createXid(xid1);

      xaRes1.start(xid1, XAResource.TMNOFLAGS);
      xaRes2.start(xid2, XAResource.TMNOFLAGS);
      conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)");

      // ensure visibility
      assertEquals(
          "1",
          getSingleIndexedValueWithQuery(
                  conn1, 1, "SELECT field1 FROM testCoordination WHERE field1=1")
              .toString());

      conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");

      // ensure visibility
      assertEquals(
          "2",
          getSingleIndexedValueWithQuery(
                  conn2, 1, "SELECT field1 FROM testCoordination WHERE field1=2")
              .toString());

      xaRes1.end(xid1, XAResource.TMSUCCESS);
      xaRes2.end(xid2, XAResource.TMSUCCESS);

      xaRes1.prepare(xid1);
      xaRes2.prepare(xid2);

      xaRes1.rollback(xid1);
      xaRes2.rollback(xid2);

      this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1");

      assertTrue(!this.rs.next());
    } finally {
      if (conn1 != null) {
        conn1.close();
      }

      if (conn2 != null) {
        conn2.close();
      }

      if (xaConn1 != null) {
        xaConn1.close();
      }

      if (xaConn2 != null) {
        xaConn2.close();
      }
    }
  }
Beispiel #11
0
  public void testSuspendableTx() throws Exception {
    if (!versionMeetsMinimum(5, 0)) {
      return;
    }

    Connection conn1 = null;

    MysqlXADataSource suspXaDs = new MysqlXADataSource();
    suspXaDs.setUrl(BaseTestCase.dbUrl);
    suspXaDs.setPinGlobalTxToPhysicalConnection(true);
    suspXaDs.setRollbackOnPooledClose(true);

    XAConnection xaConn1 = null;

    Xid xid = createXid();

    try {
      /*
       * -- works using RESUME
       * xa start 0x123,0x456;
       * select * from foo;
       * xa end 0x123,0x456;
       * xa start 0x123,0x456 resume;
       * select * from foo;
       * xa end 0x123,0x456;
       * xa commit 0x123,0x456 one phase;
       */

      xaConn1 = suspXaDs.getXAConnection();
      XAResource xaRes1 = xaConn1.getXAResource();
      conn1 = xaConn1.getConnection();
      xaRes1.start(xid, XAResource.TMNOFLAGS);
      conn1.createStatement().executeQuery("SELECT 1");
      xaRes1.end(xid, XAResource.TMSUCCESS);
      xaRes1.start(xid, XAResource.TMRESUME);
      conn1.createStatement().executeQuery("SELECT 1");
      xaRes1.end(xid, XAResource.TMSUCCESS);
      xaRes1.commit(xid, true);

      xaConn1.close();

      /*
       *
       * -- fails using JOIN
       * xa start 0x123,0x456;
       * select * from foo;
       * xa end 0x123,0x456;
       * xa start 0x123,0x456 join;
       * select * from foo;
       * xa end 0x123,0x456;
       * xa commit 0x123,0x456 one phase;
       */

      xaConn1 = suspXaDs.getXAConnection();
      xaRes1 = xaConn1.getXAResource();
      conn1 = xaConn1.getConnection();
      xaRes1.start(xid, XAResource.TMNOFLAGS);
      conn1.createStatement().executeQuery("SELECT 1");
      xaRes1.end(xid, XAResource.TMSUCCESS);
      xaRes1.start(xid, XAResource.TMJOIN);
      conn1.createStatement().executeQuery("SELECT 1");
      xaRes1.end(xid, XAResource.TMSUCCESS);
      xaRes1.commit(xid, true);
    } finally {
      if (xaConn1 != null) {
        xaConn1.close();
      }
    }
  }
Beispiel #12
0
  /**
   * Tests operation of local transactions on XAConnections when global transactions are in or not
   * in progress (follows from BUG#17401).
   *
   * @throws Exception if the testcase fails
   */
  public void testLocalTransaction() throws Exception {
    if (!versionMeetsMinimum(5, 0)) {
      return;
    }

    createTable("testLocalTransaction", "(field1 int) ENGINE=InnoDB");

    Connection conn1 = null;

    XAConnection xaConn1 = null;

    try {
      xaConn1 = getXAConnection();
      XAResource xaRes1 = xaConn1.getXAResource();
      conn1 = xaConn1.getConnection();
      assertEquals(true, conn1.getAutoCommit());
      conn1.setAutoCommit(true);
      conn1.createStatement().executeUpdate("INSERT INTO testLocalTransaction VALUES (1)");
      assertEquals(
          "1",
          getSingleIndexedValueWithQuery(conn1, 1, "SELECT field1 FROM testLocalTransaction")
              .toString());

      conn1.createStatement().executeUpdate("TRUNCATE TABLE testLocalTransaction");
      conn1.setAutoCommit(false);
      conn1.createStatement().executeUpdate("INSERT INTO testLocalTransaction VALUES (2)");
      assertEquals(
          "2",
          getSingleIndexedValueWithQuery(conn1, 1, "SELECT field1 FROM testLocalTransaction")
              .toString());
      conn1.rollback();
      assertEquals(0, getRowCount("testLocalTransaction"));

      conn1.createStatement().executeUpdate("INSERT INTO testLocalTransaction VALUES (3)");
      assertEquals(
          "3",
          getSingleIndexedValueWithQuery(conn1, 1, "SELECT field1 FROM testLocalTransaction")
              .toString());
      conn1.commit();
      assertEquals(
          "3",
          getSingleIndexedValueWithQuery(conn1, 1, "SELECT field1 FROM testLocalTransaction")
              .toString());
      conn1.commit();

      Savepoint sp = conn1.setSavepoint();
      conn1.rollback(sp);
      sp = conn1.setSavepoint("abcd");
      conn1.rollback(sp);
      Savepoint spSaved = sp;

      Xid xid = createXid();
      xaRes1.start(xid, XAResource.TMNOFLAGS);

      try {
        try {
          conn1.setAutoCommit(true);
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          conn1.commit();
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          conn1.rollback();
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          sp = conn1.setSavepoint();
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          conn1.rollback(spSaved);
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          sp = conn1.setSavepoint("abcd");
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }

        try {
          conn1.rollback(spSaved);
        } catch (SQLException sqlEx) {
          // we expect an exception here
          assertEquals("2D000", sqlEx.getSQLState());
        }
      } finally {
        xaRes1.forget(xid);
      }
    } finally {
      if (xaConn1 != null) {
        try {
          xaConn1.close();
        } catch (SQLException sqlEx) {
          // this is just busted in the server right now
        }
      }
    }
  }
Beispiel #13
0
  /**
   * Tests that XA RECOVER works as expected.
   *
   * @throws Exception if test fails
   */
  public void testRecover() throws Exception {
    if (!versionMeetsMinimum(5, 0)) {
      return;
    }

    if (versionMeetsMinimum(5, 7) && !versionMeetsMinimum(5, 7, 5)) {
      // Test is broken in 5.7.0 - 5.7.4 after server bug#14670465 fix which changed the XA RECOVER
      // output format.
      // Fixed in 5.7.5 server version
      return;
    }

    // BUG#14670465 fix broke this functionality in 5.7.1 - 5.7.2
    if (versionMeetsMinimum(5, 7, 1) && !versionMeetsMinimum(5, 7, 3)) {
      return;
    }

    XAConnection xaConn = null, recoverConn = null;

    try {
      xaConn = getXAConnection();

      Connection c = xaConn.getConnection();
      Xid xid = createXid();

      XAResource xaRes = xaConn.getXAResource();
      xaRes.start(xid, XAResource.TMNOFLAGS);
      c.createStatement().executeQuery("SELECT 1");
      xaRes.end(xid, XAResource.TMSUCCESS);
      xaRes.prepare(xid);

      // Now try and recover
      recoverConn = getXAConnection();

      XAResource recoverRes = recoverConn.getXAResource();

      Xid[] recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);

      assertTrue(recoveredXids != null);
      assertTrue(recoveredXids.length > 0);

      boolean xidFound = false;

      for (int i = 0; i < recoveredXids.length; i++) {
        if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) {
          xidFound = true;

          break;
        }
      }

      assertTrue(xidFound);

      recoverRes = recoverConn.getXAResource();

      recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN);

      assertTrue(recoveredXids != null);
      assertTrue(recoveredXids.length > 0);

      xidFound = false;

      for (int i = 0; i < recoveredXids.length; i++) {
        if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) {
          xidFound = true;

          break;
        }
      }

      assertTrue(xidFound);

      // Test flags
      recoverRes.recover(XAResource.TMSTARTRSCAN);
      recoverRes.recover(XAResource.TMENDRSCAN);
      recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);

      // This should fail
      try {
        recoverRes.recover(XAResource.TMSUCCESS);
        fail("XAException should have been thrown");
      } catch (XAException xaEx) {
        assertEquals(XAException.XAER_INVAL, xaEx.errorCode);
      }
    } finally {
      if (xaConn != null) {
        xaConn.close();
      }

      if (recoverConn != null) {
        recoverConn.close();
      }
    }
  }
 protected void tearDown() throws Exception {
   xacon_.close();
 }