Hi,
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 atrannie
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" ?>
<jndi-name>EQ-EQ5</jndi-name>
<use-java-context>false</use-java-context>
<xa-datasource-class>com.ibm.as400.access.AS400JDBCXADataSource</xa-datasource-class>
<xa-datasource-property name="User">WHATEVER</xa-datasource-property>
<xa-datasource-property name="Password">ITMAYBE</xa-datasource-property>
<xa-datasource-property name="ServerName">MACHINEA</xa-datasource-property>
<xa-datasource-property name="Libraries">*LIBL</xa-datasource-property>
<xa-datasource-property name="Naming">system</xa-datasource-property>
<track-connection-by-tx>true</track-connection-by-tx>
<prepared-statement-cache-size>100</prepared-statement-cache-size>
<isSameRM-override-value>false</isSameRM-override-value>
<check-valid-connection-sql />
- <!-- pooling parameters
--> <min-pool-size>1</min-pool-size>
<max-pool-size>50</max-pool-size>
<blocking-timeout-millis>50000</blocking-timeout-millis>
<idle-timeout-minutes>5</idle-timeout-minutes>
<type-mapping>DB2/400</type-mapping>
</metadata>
</xa-datasource>
</datasources>
<?xml version="1.0" encoding="UTF-8" ?>
<jndi-name>EQ-EQ4</jndi-name>
<use-java-context>false</use-java-context>
<xa-datasource-class>com.ibm.as400.access.AS400JDBCXADataSource</xa-datasource-class>
<xa-datasource-property name="User">WHATEVER</xa-datasource-property>
<xa-datasource-property name="Password">ITMAYBE</xa-datasource-property>
<xa-datasource-property name="ServerName">MACHINEA</xa-datasource-property>
<xa-datasource-property name="Libraries">*LIBL</xa-datasource-property>
<xa-datasource-property name="Naming">system</xa-datasource-property>
<track-connection-by-tx>true</track-connection-by-tx>
<prepared-statement-cache-size>100</prepared-statement-cache-size>
<isSameRM-override-value>false</isSameRM-override-value>
<check-valid-connection-sql />
- <!-- pooling parameters
--> <min-pool-size>1</min-pool-size>
<max-pool-size>50</max-pool-size>
<blocking-timeout-millis>50000</blocking-timeout-millis>
<idle-timeout-minutes>5</idle-timeout-minutes>
<type-mapping>DB2/400</type-mapping>
</metadata>
</xa-datasource>
</datasources>