When an XAException occurs during xa.start() or other XA operation,
because of an SQLException, what should the XAException.errorCode be?
Currently we have an errorCode of 0, regardless of the severity. Is
this correct, or should it be XAER_RMERR for SESSION_SEVERITY exceptions
or all SQLExceptions?
Here is an example where we get no current connection on xa.start()
after shutting down the database. (I informed the user that shutting
down the database in the midst of normal operations is not a good idea
as it may lead to NullPointerExceptions and other strange behavior on
other calls). They are, however, wondering about whether we should ever
see an errorCode 0 on an XAException.
Thanks
Kathey
[C:] java NoConnRepro
connectionClosed called from MyConnectionEventListner
No exception to display
Start shutdown
Shutdown complete
XAException errorCode=0
javax.transaction.xa.XAException: No current connection.
at
org.apache.derby.jdbc.EmbedXAResource.wrapInXAException(Unknown Source)
at org.apache.derby.jdbc.EmbedXAResource.start(Unknown Source)
at NoConnRepro.main(NoConnRepro.java:33)
Caused by: java.sql.SQLNonTransientConnectionException: No current
connection.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown
Source)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown
Source)
at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown
Source)
at org.apache.derby.impl.jdbc.Util.noCurrentConnection(Unknown
Source)
at
org.apache.derby.impl.jdbc.EmbedConnection.checkIfClosed(Unknown Source)
at
org.apache.derby.impl.jdbc.EmbedConnection.setupContextStack(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.rollback(Unknown
Source)
at
org.apache.derby.jdbc.EmbedPooledConnection.resetRealConnection(Unknown
Source)
... 2 more
Caused by: java.sql.SQLException: No current connection.
at
org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown
Source)
at
org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown
Source)
... 10 more
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.io.Serializable;
class utilXid implements Xid, Serializable {
private static final long serialVersionUID = 64467338100036L;
private final int format_id;
private byte[] global_id;
private byte[] branch_id;
utilXid(int xid, int b1, int b2) {
format_id = xid;
global_id = new byte[Xid.MAXGTRIDSIZE];
branch_id = new byte[Xid.MAXBQUALSIZE];
for (int i = 0; i < global_id.length; i++) {
global_id[i] = (byte) (b1 + i);
}
for (int i = 0; i < branch_id.length; i++) {
branch_id[i] = (byte) (b2 + i);
}
}
/**
* Obtain the format id part of the Xid.
* <p>
*
* @return Format identifier. O means the OSI CCR format.
**/
public int getFormatId() {
return (format_id);
}
/**
* Obtain the global transaction identifier part of XID as an array of
* bytes.
* <p>
*
* @return A byte array containing the global transaction identifier.
**/
public byte[] getGlobalTransactionId() {
return (global_id);
}
/**
* Obtain the transaction branch qualifier part of the Xid in a byte array.
* <p>
*
* @return A byte array containing the branch qualifier of the transaction.
**/
public byte[] getBranchQualifier() {
return (branch_id);
}
}
import java.sql.*;
import javax.sql.ConnectionEventListener;
import javax.sql.ConnectionEvent;
public class MyConnectionEventListener implements ConnectionEventListener{
public MyConnectionEventListener() {}
public void connectionClosed(ConnectionEvent event) {
System.out.println("connectionClosed called from
MyConnectionEventListner");
SQLException se = event.getSQLException();
displaySQLException(se);
}
public void connectionErrorOccurred(ConnectionEvent event) {
System.out.println("connectionErrorOccurred called from
MyConnectionEventListner");
SQLException se = event.getSQLException();
displaySQLException(se);
}
public void displaySQLException(SQLException se) {
if (se == null) {
System.out.println("No exception to display");
return;
}
while (se != null) {
System.out.println("SQLState=" + se.getSQLState() + " errorCode=" +
se.getErrorCode());
se.printStackTrace();
se = se.getNextException();
}
}
}
import org.apache.derby.jdbc.EmbeddedXADataSource;
import java.sql.*;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.*;
public class NoConnRepro{
public static void main(String[] args) throws Exception {
EmbeddedXADataSource ds = new EmbeddedXADataSource();
ds.setDatabaseName("wombat");
ds.setCreateDatabase("create");
XAConnection xaconn = ds.getXAConnection();
xaconn.addConnectionEventListener(new MyConnectionEventListener());
XAResource xar = xaconn.getXAResource();
Xid xid = new utilXid(1,93,18);
xar.start(xid, XAResource.TMNOFLAGS);
Connection conn = xaconn.getConnection();
Statement s = conn.createStatement();
s.executeUpdate("CREATE TABLE TAB (I INT)");
xar.end(xid, XAResource.TMSUCCESS);
xar.prepare(xid);
xar.rollback(xid);
conn.close();
System.out.println("Start shutdown");
shutdown("wombat");
System.out.println("Shutdown complete");
try {
xar.start(xid, XAResource.TMNOFLAGS);
} catch (XAException xae) {
System.out.println("XAException errorCode=" + xae.errorCode);
xae.printStackTrace();
}
conn = xaconn.getConnection();
s = conn.createStatement();
s.executeUpdate("CREATE TABLE TAB (I INT)");
xar.end(xid, XAResource.TMSUCCESS);
xar.prepare(xid);
xar.rollback(xid);
conn.close();
xaconn.close();
}
public static void shutdown(String dbname) throws SQLException {
try {
DriverManager.getConnection("jdbc:derby:" + dbname +
";shutdown=true");
throw new SQLException("Should have gotten an exception shutting
down");
} catch (SQLException se) {
if (se.getSQLState().trim().equals("08006"))
return;
throw se;
}
}
public static void displaySQLException(SQLException se) {
if (se == null) {
System.out.println("No exception to display");
return;
}
while (se != null) {
System.out.println("SQLState=" + se.getSQLState() + " errorCode=" +
se.getErrorCode());
se.printStackTrace();
se = se.getNextException();
}
}
}