db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Knut Anders Hatlen (JIRA)" <j...@apache.org>
Subject [jira] Updated: (DERBY-4232) Call XAResource.setTransactionTimeout() makes XAResource.start() fail with the client dirver
Date Wed, 24 Jun 2009 13:39:07 GMT

     [ https://issues.apache.org/jira/browse/DERBY-4232?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Knut Anders Hatlen updated DERBY-4232:
--------------------------------------

    Attachment: d4232-1a.diff

The patch d4232-1a.diff appears to fix the issue. It simply skips sending the timeout property
if something we have other flags than TMNOFLAGS. Currently, the client code will only reread
the timeout value when start(xid,TMNOFLAGS) is called, but the last timeout value read is
still sent to the server regardless of the flags. I think this is unintentional, and that
the meaning was to suppress the sending of the value as well. If start(xid,TMNOFLAGS) hasn't
been called on the XAResource before we call start() with TMJOIN, the timeout value will be
ignored with the current code too, and we don't get the XAER_PROTO exception.

(This means that we will ignore changes in the timeout value when calling start() with flags!=TMNOFLAGS,
which I wouldn't think is according to the XA specification. However, this is an existing
problem in the cases where we don't get a protocol error, so a new bug should be filed if
someone wants that addressed. My current understanding is that communicating the changed timeout
value to the server in the non-TMNOFLAGS case would require an extension to the DRDA protocol.)

> 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
>         Attachments: d4232-1a.diff, test.diff
>
>
> 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.


Mime
View raw message