Call XAResource.setTransactionTimeout() makes XAResource.start() fail with the
client dirver
--------------------------------------------------------------------------------------------
Key: DERBY-4232
URL: https://issues.apache.org/jira/browse/DERBY-4232
Project: Derby
Issue Type: Bug
Components: JDBC
Affects Versions: 10.4.2.0
Reporter: Simon Meng
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) {
}
}
}
}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.