AS400JDBCDataSource - getting started with two transactions
esther_williams May 11, 2010 2:05 PMHi,
This is the discussion started by Chris Weddell but hopefully without formatting issues.
I am trying to get started with XA using JBOSS connected to two datasources (seperate applications) on the same AS400 (DB2) database.
I have two datasources (see below) and have the following code...
package
com.misys.equation.xa.test;
import
java.sql.Connection;
import
java.sql.Statement;
import
javax.naming.InitialContext;
import
javax.sql.DataSource;
import
javax.transaction.UserTransaction;
public
class Esther {
public static void main(String[] args) { UserTransaction utx;
try
{ InitialContext initialContext =
new InitialContext(); utx = (UserTransaction) initialContext.lookup(
"UserTransaction"); DataSource dataSource1 = (DataSource) initialContext.lookup(
"EQ-EQ4"); DataSource dataSource2 = (DataSource) initialContext.lookup(
"EQ-EQ5");
// begin a trannie
utx.begin();
// ..
Connection connection1 = dataSource1.getConnection(); Statement statement1 = connection1.createStatement(); statement1.execute(
"INSERT INTO KFILEQ4/JVPF (JVHRC, JVHRD) VALUES('E01', 'EEE')"); statement1.close(); connection1.close(); Connection connection2 = dataSource2.getConnection(); Statement statement2 = connection2.createStatement(); statement2.execute(
"INSERT INTO KFILEQ4/JVPF (JVHRC, JVHRD) VALUES('E02', 'EEE')"); statement2.close(); connection2.close();
// unfortunately the following line fails
utx.commit(); System.
out.println(utx.getStatus()); }
catch (Exception e) { e.printStackTrace(); } } }
unfortunately I get the following error when i execute the commit....
14:53:50,076 INFO [STDOUT] Wed Apr 14 14:53:50:076 BST 2010 as400: XAResource B603382C-XA:RMID#49153 (30120272) : xa_end.
14:53:50,076 INFO [STDOUT] Wed Apr 14 14:53:50:076 BST 2010 as400: XAResource B603382C-XA:RMID#49153 (30120272) : xa error class = 0, return code = 0.
14:53:50,076 INFO [STDOUT] Wed Apr 14 14:53:50:076 BST 2010 as400: XAResource B603382C-XA:RMID#49153 (30120272) : xa_commit.
14:53:50,092 INFO [STDOUT] Wed Apr 14 14:53:50:092 BST 2010 as400: XAResource B603382C-XA:RMID#49153 (30120272) : xa error class = 9, return code = -6.
14:53:50,092 ERROR [STDERR]
javax.transaction.RollbackException: [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] Could not commit transaction.
14:53:50,092 ERROR [STDERR] at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(
TransactionImple.java:1426)
14:53:50,092 ERROR [STDERR] at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(
BaseTransaction.java:135)
14:53:50,092 ERROR [STDERR] at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(
BaseTransactionManagerDelegate.java:75)
14:53:50,092 ERROR [STDERR] at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(
ServerVMClientUserTransaction.java:162)
14:53:50,092 ERROR [STDERR] at com.misys.equation.ui.services.ServiceDirectory.startXATransaction(
ServiceDirectory.java:1156)
14:53:50,092 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(
Native Method)
14:53:50,092 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
14:53:50,092 ERROR [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
14:53:50,092 ERROR [STDERR] at java.lang.reflect.Method.invoke(Unknown Source)
14:53:50,092 ERROR [STDERR] at org.apache.axis.providers.java.RPCProvider.invokeMethod(
RPCProvider.java:397)
14:53:50,092 ERROR [STDERR] at org.apache.axis.providers.java.RPCProvider.processMessage(
RPCProvider.java:186)
14:53:50,092 ERROR [STDERR] at org.apache.axis.providers.java.JavaProvider.invoke(
JavaProvider.java:323)
14:53:50,092 ERROR [STDERR] at org.apache.axis.strategies.InvocationStrategy.visit(
InvocationStrategy.java:32)
14:53:50,092 ERROR [STDERR] at org.apache.axis.SimpleChain.doVisiting(
SimpleChain.java:118)
14:53:50,092 ERROR [STDERR] at org.apache.axis.SimpleChain.invoke(
SimpleChain.java:83)
14:53:50,092 ERROR [STDERR] at org.apache.axis.handlers.soap.SOAPService.invoke(
SOAPService.java:454)
14:53:50,092 ERROR [STDERR] at org.apache.axis.server.AxisServer.invoke(
AxisServer.java:281)
14:53:50,092 ERROR [STDERR] at org.apache.axis.transport.http.AxisServlet.doPost(
AxisServlet.java:699)
14:53:50,092 ERROR [STDERR] at javax.servlet.http.HttpServlet.service(
HttpServlet.java:637)
14:53:50,092 ERROR [STDERR] at org.apache.axis.transport.http.AxisServletBase.service(
AxisServletBase.java:327)
14:53:50,092 ERROR [STDERR] at javax.servlet.http.HttpServlet.service(
HttpServlet.java:717)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(
ApplicationFilterChain.java:290)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.doFilter(
ApplicationFilterChain.java:206)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(
ReplyHeaderFilter.java:96)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(
ApplicationFilterChain.java:235)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.ApplicationFilterChain.doFilter(
ApplicationFilterChain.java:206)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.StandardWrapperValve.invoke(
StandardWrapperValve.java:235)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.StandardContextValve.invoke(
StandardContextValve.java:191)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(
SecurityAssociationValve.java:190)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.security.JaccContextValve.invoke(
JaccContextValve.java:92)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(
SecurityContextEstablishmentValve.java:126)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(
SecurityContextEstablishmentValve.java:70)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.StandardHostValve.invoke(
StandardHostValve.java:127)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.valves.ErrorReportValve.invoke(
ErrorReportValve.java:102)
14:53:50,092 ERROR [STDERR] at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(
CachedConnectionValve.java:158)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.core.StandardEngineValve.invoke(
StandardEngineValve.java:109)
14:53:50,092 ERROR [STDERR] at org.apache.catalina.connector.CoyoteAdapter.service(
CoyoteAdapter.java:330)
14:53:50,092 ERROR [STDERR] at org.apache.coyote.http11.Http11Processor.process(
Http11Processor.java:829)
14:53:50,092 ERROR [STDERR] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(
Http11Protocol.java:601)
14:53:50,092 ERROR [STDERR] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(
JIoEndpoint.java:447)
14:53:50,092 ERROR http://community.jboss.org/message/537429#537429/STDERR at java.lang.Thread.run(Unknown Source)
Now when i run the following code I don't get a problem....
package
com.misys.equation.xa.test;
import
java.io.Serializable;
import
java.sql.Connection;
import
java.sql.SQLException;
import
java.sql.Statement;
import
java.util.Arrays;
import
java.util.Random;
import
javax.sql.XAConnection;
import
javax.transaction.xa.XAException;
import
javax.transaction.xa.XAResource;
import
javax.transaction.xa.Xid;
import
com.ibm.as400.access.AS400JDBCXADataSource;
import
com.ibm.as400.access.AS400JDBCXAResource;
import
com.misys.equation.common.utilities.Toolbox;
public
class Esther2 {
// This attribute is used to store cvs version information.
public static final String _revision = "$Id: FileProcessor.java,v 1.6 2009/09/16 16:13:27 esther.williams Exp $"; String
user1 = "whatever"; String
password1 = "itmaybe"; String
system1 = "machineA"; String
user2 = "whatever"; String
password2 = "itmaybe"; String
system2 = "machineA"; String
library = "*LIBL"; AS400JDBCXADataSource
xaDataSource1 = null; XAConnection
xaConnection1 = null; XAResource
xaResource1 = null; XidImpl
xid = null; Connection
connection1 = null; Statement
statement1 = null; AS400JDBCXADataSource
xaDataSource2 = null; XAConnection
xaConnection2 = null; XAResource
xaResource2 = null; AS400JDBCXAResource
a;
// private XidImpl xid2 = null;
Connection
connection2 = null; Statement
statement2 = null;
private Esther2() { }
public static void main(String[] args) { System.
out.println("Proceeding with test..."); Esther2 test =
new Esther2(); test.test(); }
private void test() {
try
{
xaDataSource1 = new AS400JDBCXADataSource();
xaDataSource1.setServerName(system1);
xaDataSource1.setUser(user1);
xaDataSource1.setPassword(password1);
xaDataSource1.setLibraries(library);
xaDataSource1.setNaming("system");
xaDataSource1.setTranslateBinary(false);
xaDataSource1.setTrace(true);
xaDataSource2 = new AS400JDBCXADataSource();
xaDataSource2.setServerName(system2);
xaDataSource2.setUser(user2);
xaDataSource2.setPassword(password2);
xaDataSource2.setLibraries(library);
xaDataSource2.setNaming("system");
xaDataSource2.setTranslateBinary(false);
xaDataSource2.setTrace(true);
xaConnection1 = xaDataSource1.getXAConnection();
xaConnection2 = xaDataSource2.getXAConnection();
xaResource1 = xaConnection1.getXAResource();
xaResource2 = xaConnection2.getXAResource();
xid = new XidImpl(new byte[] { 0x0d }, new byte[] { 0x0b });
xaResource1.start(xid, XAResource.TMNOFLAGS);
// Need to decide whether to join based on whether the resources have the same resource manager
// if the are the same then the prepares, commits and rollbacks should only be executed on
// the first resource
if (xaResource1.isSameRM(xaResource2)) {
xaResource2.start(xid, XAResource.TMJOIN); }
else
{
xaResource2.start(xid, XAResource.TMNOFLAGS); }
// Do some SQL on connection 1
connection1 = xaConnection1.getConnection();
statement1 = connection1.createStatement();
statement1.executeUpdate("INSERT INTO KFILEQ4/JVPF (JVHRC, JVHRD) VALUES('X01', 'X01D')");
// Do some SQL on connection 2
connection2 = xaConnection2.getConnection();
statement2 = connection2.createStatement();
statement2.executeUpdate("INSERT INTO KFILEQ4/JVPF (JVHRC, JVHRD) VALUES('X02', 'X02D')");
// tell the resources that we have successfully finished doing the work,
// need to consider what to do if the SQL had gone wrong!
xaResource1.end(xid, XAResource.TMSUCCESS);
xaResource2.end(xid, XAResource.TMSUCCESS);
if (xaResource1.isSameRM(xaResource2)) {
// only need to prepare on the first resource
int ret1 = xaResource1.prepare(xid);
// int ret2 = xaResource2.prepare(xid);
// only need to commit on the first resource
xaResource1.commit(xid, false);
// xaResource2.commit(xid, false);
}
else
{
int ret1 = xaResource1.prepare(xid);
int ret2 = xaResource2.prepare(xid);
xaResource1.commit(xid, false);
xaResource2.commit(xid, false); } }
catch (XAException e) { e.printStackTrace(); }
catch (SQLException e) { e.printStackTrace(); }
finally
{
try
{
statement1.close();
statement2.close();
connection1.close();
connection2.close();
xaConnection1.close();
xaConnection2.close(); }
catch (Exception e2) {
// TODO: handle exception
} } }
public static class XidImpl implements Serializable, Xid {
private static final long serialVersionUID = 1L;
private static Random random = new Random();
private final int formatId = 876;
private final byte[] globalTransactionId;
private final byte[] branchQualifier;
private transient String cachedToString;
private transient int cachedHashCode;
public XidImpl() {
globalTransactionId = new byte[10];
random.nextBytes(globalTransactionId);
branchQualifier = new byte[10];
random.nextBytes(branchQualifier); }
public XidImpl(byte[] globalTransactionId, byte[] branchQualifier) {
this.globalTransactionId = globalTransactionId;
this.branchQualifier = branchQualifier; }
public int getFormatId() {
return formatId; }
public byte[] getGlobalTransactionId() {
return globalTransactionId; }
public byte[] getBranchQualifier() {
return branchQualifier; }
@Override
public boolean equals(Object object) {
if (object == this)
return true;
if (object == null || object instanceof Xid == false)
return false; Xid other = (Xid) object;
return (formatId == other.getFormatId() && Arrays.equals(globalTransactionId, other.getGlobalTransactionId()) && Arrays .equals(
branchQualifier, other.getBranchQualifier())); }
@Override
public int hashCode() {
if (cachedHashCode == 0) {
cachedHashCode = formatId;
for (int j = 0; j < globalTransactionId.length; ++j)
cachedHashCode += globalTransactionId[j]; }
return cachedHashCode; }
@Override
public String toString() {
if (cachedToString == null) { StringBuffer buffer =
new StringBuffer(); buffer.append(
"XidImpl[FormatId=").append(getFormatId()); buffer.append(
" GlobalId=x'").append(Toolbox.cvtBytesToHexString(getGlobalTransactionId())); buffer.append(
"' BranchQual=x'").append(Toolbox.cvtBytesToHexString(getBranchQualifier())); buffer.append(
"']");
cachedToString = buffer.toString(); }
return cachedToString; } } }
Note there is an extra "end" for the secound resource and a "prepare" that i don't see logged in the jboss example.
Any ideas?
<?xml version="1.0" encoding="UTF-8" ?>