I'm using tyrex 1.0, tomcat 4.1, Oracle 8.1.7 and thin driver. Within a transaction if i create no of statements on same connection object
and create a few connections within a transaction, the commit hangs while priting following messages repeatedly..
If you open one less connection the whole thing works. Is it Oracle or Tyrex problem?
We have fixed the problem. Actually a circular list was getting created in this particular scenario. We have fixed TransactionImpl.enlistResource method. Here is the modified method. Can you guys verify it?
if ( xaResource == null )
throw new IllegalArgumentException( "Argument xaResource is null" );
// Proper notification for transactions that timed out.
if ( _timedOut )
throw new RollbackException( Messages.message( "tyrex.tx.timedOut" ) );
// Check the status of the transaction and act accordingly.
switch ( _status ) {
case STATUS_ACTIVE:
// Transaction is active, we can enlist the resource.
break;
case STATUS_MARKED_ROLLBACK:
// Transaction marked for rollback, we cannot possibly enlist.
throw new RollbackException( Messages.message( "tyrex.tx.markedRollback" ) );
case STATUS_PREPARED:
case STATUS_PREPARING:
case STATUS_COMMITTING:
// Transaction is preparing, cannot enlist resource.
throw new IllegalStateException( Messages.message( "tyrex.tx.inCommit" ) );
case STATUS_ROLLEDBACK:
case STATUS_ROLLING_BACK:
case STATUS_COMMITTED:
case STATUS_NO_TRANSACTION:
case STATUS_UNKNOWN:
default:
throw new IllegalStateException( Messages.message( "tyrex.tx.inactive" ) );
}
if ( _enlisted != null ) {
// Look if we alredy got the resource enlisted. If the
// resource was suspended, we just resume it and go out.
// If the resource was started, we do not enlist it a
// second time.
resHolder = _enlisted;
previousResHolder = null;
while ( resHolder != null ) {
System.out.println("inside enlisted................ while ( resHolder != null )..............");
if ( resHolder._xaResource == xaResource ) {
if ( resHolder._endFlag == XAResource.TMSUSPEND ) {
try {
xaResource.start( resHolder._xid, XAResource.TMRESUME );
resHolder._endFlag = XAResource.TMNOFLAGS;
System.out.println(" ................return true...........................10");
return true;
} catch ( XAException except ) {
except.printStackTrace();
throw new NestedSystemException( except );
} catch ( Exception except ) {
except.printStackTrace();
throw new NestedSystemException( except );
}
} else {
System.out.println("................return false...............................20");
return false;
}
}
previousResHolder = resHolder;
System.out.println("................resHolder = resHolder._nextHolder...............................30");
resHolder = resHolder._nextHolder;
}
// check the delisted
resHolder = _delisted;
InternalXAResourceHolder tmp=null;
while ( resHolder != null ) {
System.out.println("inside delisted................ while ( resHolder != null )..............");
if ( resHolder._xaResource == xaResource ) {
if ( resHolder._endFlag == XAResource.TMSUCCESS ) {
try {
xaResource.start( resHolder._xid, XAResource.TMJOIN );
resHolder._endFlag = XAResource.TMNOFLAGS;
I'm using tyrex 1.0, tomcat 4.1, Oracle 8.1.7 and thin driver. Within a transaction if i create no of statements on same connection object
and create a few connections within a transaction, the commit hangs while priting following messages repeatedly..
If you open one less connection the whole thing works. Is it Oracle or Tyrex problem?
.....
.....
.....
.....
24 Sep 2002 19:36:36:tyrex.resource.my-datasource:DEBUG XAConnection: unused tra
nsaction ended -2392
140762 [Thread-5] DEBUG resource.my-datasource - XAConnection: unused transacti
on ended -2392
24 Sep 2002 19:36:36:tyrex.resource.my-datasource:DEBUG XAConnection: unused tra
nsaction ended -2393
140772 [Thread-5] DEBUG resource.my-datasource - XAConnection: unused transacti
on ended -2393
24 Sep 2002 19:36:36:tyrex.resource.my-datasource:DEBUG XAConnection: unused tra
nsaction ended -2394
140792 [Thread-5] DEBUG resource.my-datasource - XAConnection: unused transacti
on ended -2394
24 Sep 2002 19:36:36:tyrex.resource.my-datasource:DEBUG XAConnection: unused tra
nsaction ended -2395
.....
.....
.....
.....
===================================End-Exception======================================
====================================Start-Code=========================================
<%@ page language="java" %>
<%@ page import="net.etouch.wf.pipeline.*, javax.sql.*, java.sql.*, javax.naming.*, tyrex.tm.TransactionDomain,javax.transaction.*, java.io.*" %>
<%
UserTransaction tx1 = null;
UserTransaction tx2 = null;
TransactionManager tm = null;
TransactionDomain domain = null;
int updCount = 0;
try {
//Context initContext = new InitialContext();
//Context envContext = (Context)initContext.lookup("java:/comp/env");
// DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
// Connection conn = ds.getConnection();
oracle.jdbc.driver.OracleLog.setLogWriter(new PrintWriter(new FileWriter("my.log")));
InitialContext initCtx = new InitialContext();
//tx1 = (UserTransaction) initCtx.lookup("java:comp/UserTransaction");
tx2 = (UserTransaction) initCtx.lookup("java:comp/UserTransaction");
domain = TransactionDomain.getDomain("myDomain");
//domain.recover();
tm = domain.getTransactionManager();
//tm = (TransactionManager) initCtx.lookup("java:comp/TransactionManager");
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/my-datasource");
//DataSource ds = (DataSource)domain.getResources().getResource("my-datasource").getClientFactory();
tx2.begin();
Connection conn = ds.getConnection();
System.out.println("1.........................");
//Connection conn101 = ds.getConnection();
Statement st101 = conn.createStatement();
ResultSet rs101 = st101.executeQuery( "SELECT * FROM WF_WORKFLOW" );
if ( rs101.next() ) {
out.println( "<p>Current value: " + rs101.getString(1) );
}
rs101.close();
rs101 = null;
st101.close();
st101 = null;
//conn101.close();
//conn101 = null;
//Connection conn102 = ds.getConnection();
Statement st102 = conn.createStatement();
ResultSet rs102 = st102.executeQuery( "SELECT * FROM WF_WORKFLOW" );
if ( rs102.next() ) {
out.println( "<p>Current value: " + rs102.getString(1) );
}
rs102.close();
rs102 = null;
st102.close();
st102 = null;
//conn102.close();
//conn102 = null;
System.out.println("2.........................");
//Connection conn103 = ds.getConnection();
Statement st103 = conn.createStatement();
ResultSet rs103 = st103.executeQuery( "SELECT * FROM WF_ACTION" );
if ( rs103.next() ) {
out.println( "<p>Current value: " + rs103.getString(1) );
}
rs103.close();
rs103 = null;
st103.close();
st103 = null;
//conn103.close();
//conn103 = null;
//Connection conn104 = ds.getConnection();
Statement st104 = conn.createStatement();
ResultSet rs104 = st104.executeQuery( "SELECT * FROM WF_STATE" );
if ( rs104.next() ) {
out.println( "<p>Current value: " + rs104.getString(1) );
}
rs104.close();
rs104 = null;
st104.close();
st104 = null;
//conn104.close();
//conn104 = null;
System.out.println("3.........................");
//Thread.sleep(72000);
//Connection conn1 = ds.getConnection();
Statement st1 = conn.createStatement();
updCount = st1.executeUpdate( "insert into WF_USER values ('" + "k1" + "')" );
out.println( "updCount1: " +updCount );
st1.close();
st1 = null;
//conn1.close();
//conn1 = null;
//Connection conn2 = ds.getConnection();
Statement st2 = conn.createStatement();
updCount = st2.executeUpdate( "insert into WF_USER values ('" + "k2" + "')" );
out.println( "updCount2: " +updCount );
st2.close();
st2 = null;
//conn2.close();
//conn2 = null;
//Connection conn3 = ds.getConnection();
Statement st3 = conn.createStatement();
updCount = st3.executeUpdate( "insert into WF_USER values ('" + "k3" + "')" );
out.println( "updCount3: " +updCount );
st3.close();
st3 = null;
//conn3.close();
//conn3 = null;
System.out.println("4........................");
//Connection conn4 = ds.getConnection();
Statement st4 = conn.createStatement();
updCount = st4.executeUpdate( "insert into WF_USER values ('" + "k4" + "')" );
out.println( "updCount4: " +updCount );
st4.close();
st4 = null;
//conn4.close();
//conn4 = null;
//Connection conn5 = ds.getConnection();
Statement st5 = conn.createStatement();
updCount = st5.executeUpdate( "insert into WF_USER values ('" + "k5" + "')" );
out.println( "updCount5: " +updCount );
st5.close();
//conn5.close();
// Connection conn6 = ds.getConnection();
Statement st6 = conn.createStatement();
updCount = st6.executeUpdate( "insert into WF_USER values ('" + "k6" + "')" );
out.println( "updCount6: " +updCount );
st6.close();
//conn6.close();
//Connection conn7 = ds.getConnection();
Statement st7 = conn.createStatement();
updCount = st7.executeUpdate( "insert into WF_USER values ('" + "k7" + "')" );
out.println( "updCount7: " +updCount );
st7.close();
//conn7.close();
//Connection conn8 = ds.getConnection();
Statement st8 = conn.createStatement();
updCount = st8.executeUpdate( "insert into WF_USER values ('" + "k8" + "')" );
out.println( "updCount8: " +updCount );
st8.close();
//conn8.close();
//Connection conn9 = ds.getConnection();
Statement st9 = conn.createStatement();
updCount = st9.executeUpdate( "insert into WF_USER values ('" + "k9" + "')" );
out.println( "updCount9: " +updCount );
st9.close();
//conn9.close();
System.out.println("5........................");
//Connection conn10 = ds.getConnection();
Statement st10 = conn.createStatement();
updCount = st10.executeUpdate( "insert into WF_USER values ('" + "k10" + "')" );
out.println( "updCount10: " +updCount );
st10.close();
//conn10.close();
//Connection conn11 = ds.getConnection();
Statement st11 = conn.createStatement();
updCount = st11.executeUpdate( "insert into WF_USER values ('" + "k11" + "')" );
out.println( "updCount11: " +updCount );
st11.close();
//conn11.close();
//Connection conn12 = ds.getConnection();
Statement st12 = conn.createStatement();
updCount = st12.executeUpdate( "insert into WF_USER values ('" + "k12" + "')" );
out.println( "updCount12: " +updCount );
st12.close();
//conn12.close();
//============code works if you do not open conn13====================
Connection conn13 = ds.getConnection();
Statement st13 = conn.createStatement();
updCount = st13.executeUpdate( "insert into WF_USER values ('" + "k13" + "')" );
out.println( "updCount13: " +updCount );
st13.close();
conn13.close();
Connection conn14 = ds.getConnection();
Statement st14 = conn.createStatement();
updCount = st14.executeUpdate( "insert into WF_USER values ('" + "k14" + "')" );
out.println( "updCount14: " +updCount );
st14.close();
conn14.close();
/* Transaction txn = tm.suspend();
tx1.begin();
Connection conn15 = ds.getConnection();
Statement st15 = conn15.createStatement();
updCount = st15.executeUpdate( "insert into WF_USER values ('" + "k15" + "')" );
out.println( "updCount15: " +updCount );
st15.close();
conn15.close();
tx1.commit();
Connection conn16 = ds.getConnection();
conn16.setAutoCommit(false);
Statement st16 = conn16.createStatement();
updCount = st16.executeUpdate( "insert into WF_USER values ('" + "k16" + "')" );
out.println( "updCount16: " +updCount );
st16.close();
conn16.commit();
conn16.close();
tm.resume(txn);
*/
System.out.println("6........................");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k1" + "'" );
if ( rs.next() ) {
out.println( "<p>Current value: " + rs.getString(1) );
}
PreparedStatement st0 = conn.prepareStatement("SELECT * FROM WF_USER where USERID = '" + "k2" + "'");
//ResultSet rs0 = st0.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k2" + "'" );
ResultSet rs0 = st0.executeQuery();
if ( rs0.next() ) {
out.println( "<p>Current value: " + rs0.getString(1) );
}
rs0.close();
rs0 = null;
st0.close();
st0 = null;
rs.close();
rs = null;
st.close();
st = null;
conn.close();
conn = null;
try {
System.out.println("Calling commit.........................");
tx2.commit();
}
catch(Exception ex)
{ex.printStackTrace();}
}
catch(Exception e) {
e.printStackTrace();
try {
tx2.rollback();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
/*
TransactionDomain domain = null;
// Create a transaction domain using
// a domain configuration file
try {
domain = TransactionDomain.createDomain( "e:/tomcat4.1/webapps/wf/web-inf/classes/domain-config.xml" );
} catch ( DomainConfigurationException except ) {
// Domain cannot be created, handle error
except.printStackTrace();
}
// Recover all resources used in the domain
try {
domain.recover();
} catch ( RecoveryException except ) {
while ( except != null ) {
System.out.println( "Recovery error: " + except );
except = except.getNextException();
}
}
// Domain is now active and ready for use
try {
RuntimeContext runCtx;
Context jndiCtx;
Resources resources;
DataSource dataSource;
// Create a new context
runCtx = RuntimeContext.newRuntimeContext();
// Create the context 'comp/env/jdbc'
jndiCtx = runCtx.getEnvContext();
jndiCtx = jndiCtx.createSubcontext( "comp" );
jndiCtx = jndiCtx.createSubcontext( "env" );
jndiCtx = jndiCtx.createSubcontext( "jdbc" );
// Obtain resources from the transaction domain
// Obtain the client factory for 'db1'
resources = TransactionDomain.getDomain( "myDomain" ).getResources();
dataSource = (DataSource) resources.getResource( "my-datasource" );
// Bind 'db1' as 'comp/env/jdbc/myDb'
jndiCtx.bind( "my-datasource", dataSource );
// Associate the runtime context with
// the current thread
RuntimeContext.setRuntimeContext( runCtx );
// Dissociate the runtime context with
// the current thread
RuntimeContext.unsetRuntimeContext();
// Discard the runtime context
runCtx.cleanup();
}
catch(Exception e) {
e.printStackTrace();
}
*/
%>
<html>
<head>
</head>
<body>
Testing
</body>
</html>
====================================End-Code=========================================
====================================Server.xml Entry=========================================
<Context path="/wf" docBase="wf" debug="0"
reloadable="true" crossContext="true">
<Environment name="tyrexDomainConfig" type="java.lang.String" value="domain-config.xml"/>
<Environment name="tyrexDomainName" type="java.lang.String" value="myDomain"/>
<Resource name="my-datasource" auth="Container" type="tyrex.resource.Resource"/>
<ResourceParams name="my-datasource">
<parameter>
<name>name</name>
<value>my-datasource</value>
</parameter>
</ResourceParams>
</Context>
====================================End -Server.xml Entry=========================================
===================================domain-config.xml=========================================
<domain>
<name>myDomain</name>
<timeout>120</timeout>
<resources>
<dataSource>
<name>my-datasource</name>
<jar>e:/tomcat4.1/common/lib/tyrex-1.0.jar</jar>
<class>tyrex.resource.jdbc.xa.EnabledDataSource</class>
<config>
<user>fac</user>
<password>fac</password>
<driverClassName>oracle.jdbc.driver.OracleDriver</driverClassName>
<driverName>jdbc:oracle:thin:@kedar:1521:ora817</driverName>
</config>
<limits>
<maximum>30</maximum>
<timeout>200</timeout>
<trace>False</trace>
</limits>
</dataSource>
</resources>
</domain>
===================================end - domain-config.xml=========================================
<%@ page language="java" %>
<%@ page import="net.etouch.wf.pipeline.*, javax.sql.*, java.sql.*, javax.naming.*, tyrex.tm.TransactionDomain,javax.transaction.*, java.io.*" %>
<%
UserTransaction tx1 = null;
UserTransaction tx2 = null;
TransactionManager tm = null;
TransactionDomain domain = null;
int updCount = 0;
try {
oracle.jdbc.driver.OracleLog.setLogWriter(new PrintWriter(new FileWriter("my.log")));
InitialContext initCtx = new InitialContext();
tx2 = (UserTransaction) initCtx.lookup("java:comp/UserTransaction");
domain = TransactionDomain.getDomain("myDomain");
tm = domain.getTransactionManager();
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/my-datasource");
tx2.begin();
Connection conn = ds.getConnection();
System.out.println("1.........................");
Statement st101 = conn.createStatement();
ResultSet rs101 = st101.executeQuery( "SELECT * FROM WF_WORKFLOW" );
if ( rs101.next() ) {
out.println( "<p>Current value: " + rs101.getString(1) );
}
rs101.close();
rs101 = null;
st101.close();
st101 = null;
Statement st102 = conn.createStatement();
ResultSet rs102 = st102.executeQuery( "SELECT * FROM WF_WORKFLOW" );
if ( rs102.next() ) {
out.println( "<p>Current value: " + rs102.getString(1) );
}
rs102.close();
rs102 = null;
st102.close();
st102 = null;
System.out.println("2.........................");
Statement st103 = conn.createStatement();
ResultSet rs103 = st103.executeQuery( "SELECT * FROM WF_ACTION" );
if ( rs103.next() ) {
out.println( "<p>Current value: " + rs103.getString(1) );
}
rs103.close();
rs103 = null;
st103.close();
st103 = null;
Statement st104 = conn.createStatement();
ResultSet rs104 = st104.executeQuery( "SELECT * FROM WF_STATE" );
if ( rs104.next() ) {
out.println( "<p>Current value: " + rs104.getString(1) );
}
rs104.close();
rs104 = null;
st104.close();
st104 = null;
System.out.println("3.........................");
Statement st1 = conn.createStatement();
updCount = st1.executeUpdate( "insert into WF_USER values ('" + "k1" + "')" );
out.println( "updCount1: " +updCount );
st1.close();
st1 = null;
Statement st2 = conn.createStatement();
updCount = st2.executeUpdate( "insert into WF_USER values ('" + "k2" + "')" );
out.println( "updCount2: " +updCount );
st2.close();
st2 = null;
Statement st3 = conn.createStatement();
updCount = st3.executeUpdate( "insert into WF_USER values ('" + "k3" + "')" );
out.println( "updCount3: " +updCount );
st3.close();
st3 = null;
System.out.println("4........................");
Statement st4 = conn.createStatement();
updCount = st4.executeUpdate( "insert into WF_USER values ('" + "k4" + "')" );
out.println( "updCount4: " +updCount );
st4.close();
st4 = null;
Statement st5 = conn.createStatement();
updCount = st5.executeUpdate( "insert into WF_USER values ('" + "k5" + "')" );
out.println( "updCount5: " +updCount );
st5.close();
Statement st6 = conn.createStatement();
updCount = st6.executeUpdate( "insert into WF_USER values ('" + "k6" + "')" );
out.println( "updCount6: " +updCount );
st6.close();
Statement st7 = conn.createStatement();
updCount = st7.executeUpdate( "insert into WF_USER values ('" + "k7" + "')" );
out.println( "updCount7: " +updCount );
st7.close();
Statement st8 = conn.createStatement();
updCount = st8.executeUpdate( "insert into WF_USER values ('" + "k8" + "')" );
out.println( "updCount8: " +updCount );
st8.close();
Statement st9 = conn.createStatement();
updCount = st9.executeUpdate( "insert into WF_USER values ('" + "k9" + "')" );
out.println( "updCount9: " +updCount );
st9.close();
System.out.println("5........................");
Statement st10 = conn.createStatement();
updCount = st10.executeUpdate( "insert into WF_USER values ('" + "k10" + "')" );
out.println( "updCount10: " +updCount );
st10.close();
Statement st11 = conn.createStatement();
updCount = st11.executeUpdate( "insert into WF_USER values ('" + "k11" + "')" );
out.println( "updCount11: " +updCount );
st11.close();
/*
Statement st12 = conn.createStatement();
updCount = st12.executeUpdate( "insert into WF_USER values ('" + "k12" + "')" );
out.println( "updCount12: " +updCount );
st12.close();
*/
//Comment the following block to make it work
//=================Start-block=========================
Connection conn13 = ds.getConnection();
Statement st13 = conn.createStatement();
updCount = st13.executeUpdate( "insert into WF_USER values ('" + "k13" + "')" );
out.println( "updCount13: " +updCount );
st13.close();
conn13.close();
//=================End-block=========================
Connection conn14 = ds.getConnection();
Statement st14 = conn.createStatement();
updCount = st14.executeUpdate( "insert into WF_USER values ('" + "k14" + "')" );
out.println( "updCount14: " +updCount );
st14.close();
conn14.close();
System.out.println("6........................");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k1" + "'" );
if ( rs.next() ) {
out.println( "<p>Current value: " + rs.getString(1) );
}
PreparedStatement st0 = conn.prepareStatement("SELECT * FROM WF_USER where USERID = '" + "k2" + "'");
//ResultSet rs0 = st0.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k2" + "'" );
ResultSet rs0 = st0.executeQuery();
if ( rs0.next() ) {
out.println( "<p>Current value: " + rs0.getString(1) );
}
rs0.close();
rs0 = null;
st0.close();
st0 = null;
rs.close();
rs = null;
st.close();
st = null;
conn.close();
conn = null;
try {
System.out.println("Calling commit.........................");
tx2.commit();
}
catch(Exception ex)
{ex.printStackTrace();}
}
catch(Exception e) {
e.printStackTrace();
try {
tx2.rollback();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
%>
<html>
<head>
</head>
<body>
Testing
</body>
</html>
CREATE TABLE WF_USER (
USERID VARCHAR2 (100) NOT NULL,
CONSTRAINT PK_WF_USER
PRIMARY KEY ( USERID )
USING INDEX
TABLESPACE USERS PCTFREE 10
STORAGE ( INITIAL 128K NEXT 128K PCTINCREASE 0 ))
<%@ page language="java" %>
<%@ page import="net.etouch.wf.pipeline.*, javax.sql.*, java.sql.*, javax.naming.*, tyrex.tm.TransactionDomain,javax.transaction.*, java.io.*" %>
<%
UserTransaction tx1 = null;
UserTransaction tx2 = null;
TransactionManager tm = null;
TransactionDomain domain = null;
int updCount = 0;
try {
oracle.jdbc.driver.OracleLog.setLogWriter(new PrintWriter(new FileWriter("my.log")));
InitialContext initCtx = new InitialContext();
tx2 = (UserTransaction) initCtx.lookup("java:comp/UserTransaction");
domain = TransactionDomain.getDomain("myDomain");
tm = domain.getTransactionManager();
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/my-datasource");
tx2.begin();
Connection conn = ds.getConnection();
System.out.println("1.........................");
Statement st101 = conn.createStatement();
ResultSet rs101 = st101.executeQuery( "SELECT * FROM WF_USER" );
if ( rs101.next() ) {
out.println( "<p>Current value: " + rs101.getString(1) );
}
rs101.close();
rs101 = null;
st101.close();
st101 = null;
Statement st102 = conn.createStatement();
ResultSet rs102 = st102.executeQuery( "SELECT * FROM WF_USER" );
if ( rs102.next() ) {
out.println( "<p>Current value: " + rs102.getString(1) );
}
rs102.close();
rs102 = null;
st102.close();
st102 = null;
System.out.println("2.........................");
Statement st103 = conn.createStatement();
ResultSet rs103 = st103.executeQuery( "SELECT * FROM WF_USER" );
if ( rs103.next() ) {
out.println( "<p>Current value: " + rs103.getString(1) );
}
rs103.close();
rs103 = null;
st103.close();
st103 = null;
Statement st104 = conn.createStatement();
ResultSet rs104 = st104.executeQuery( "SELECT * FROM WF_USER" );
if ( rs104.next() ) {
out.println( "<p>Current value: " + rs104.getString(1) );
}
rs104.close();
rs104 = null;
st104.close();
st104 = null;
System.out.println("3.........................");
Statement st1 = conn.createStatement();
updCount = st1.executeUpdate( "insert into WF_USER values ('" + "k1" + "')" );
out.println( "updCount1: " +updCount );
st1.close();
st1 = null;
Statement st2 = conn.createStatement();
updCount = st2.executeUpdate( "insert into WF_USER values ('" + "k2" + "')" );
out.println( "updCount2: " +updCount );
st2.close();
st2 = null;
Statement st3 = conn.createStatement();
updCount = st3.executeUpdate( "insert into WF_USER values ('" + "k3" + "')" );
out.println( "updCount3: " +updCount );
st3.close();
st3 = null;
System.out.println("4........................");
Statement st4 = conn.createStatement();
updCount = st4.executeUpdate( "insert into WF_USER values ('" + "k4" + "')" );
out.println( "updCount4: " +updCount );
st4.close();
st4 = null;
Statement st5 = conn.createStatement();
updCount = st5.executeUpdate( "insert into WF_USER values ('" + "k5" + "')" );
out.println( "updCount5: " +updCount );
st5.close();
Statement st6 = conn.createStatement();
updCount = st6.executeUpdate( "insert into WF_USER values ('" + "k6" + "')" );
out.println( "updCount6: " +updCount );
st6.close();
Statement st7 = conn.createStatement();
updCount = st7.executeUpdate( "insert into WF_USER values ('" + "k7" + "')" );
out.println( "updCount7: " +updCount );
st7.close();
Statement st8 = conn.createStatement();
updCount = st8.executeUpdate( "insert into WF_USER values ('" + "k8" + "')" );
out.println( "updCount8: " +updCount );
st8.close();
Statement st9 = conn.createStatement();
updCount = st9.executeUpdate( "insert into WF_USER values ('" + "k9" + "')" );
out.println( "updCount9: " +updCount );
st9.close();
System.out.println("5........................");
Statement st10 = conn.createStatement();
updCount = st10.executeUpdate( "insert into WF_USER values ('" + "k10" + "')" );
out.println( "updCount10: " +updCount );
st10.close();
Statement st11 = conn.createStatement();
updCount = st11.executeUpdate( "insert into WF_USER values ('" + "k11" + "')" );
out.println( "updCount11: " +updCount );
st11.close();
/*
Statement st12 = conn.createStatement();
updCount = st12.executeUpdate( "insert into WF_USER values ('" + "k12" + "')" );
out.println( "updCount12: " +updCount );
st12.close();
*/
//Comment the following block to make it work
//=================Start-block=========================
Connection conn13 = ds.getConnection();
/*
Statement st13 = conn.createStatement();
updCount = st13.executeUpdate( "insert into WF_USER values ('" + "k13" + "')" );
out.println( "updCount13: " +updCount );
st13.close();
*/
conn13.close();
//=================End-block=========================
Connection conn14 = ds.getConnection();
Statement st14 = conn.createStatement();
updCount = st14.executeUpdate( "insert into WF_USER values ('" + "k14" + "')" );
out.println( "updCount14: " +updCount );
st14.close();
conn14.close();
System.out.println("6........................");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k1" + "'" );
if ( rs.next() ) {
out.println( "<p>Current value: " + rs.getString(1) );
}
PreparedStatement st0 = conn.prepareStatement("SELECT * FROM WF_USER where USERID = '" + "k2" + "'");
//ResultSet rs0 = st0.executeQuery( "SELECT * FROM WF_USER where USERID = '" + "k2" + "'" );
ResultSet rs0 = st0.executeQuery();
if ( rs0.next() ) {
out.println( "<p>Current value: " + rs0.getString(1) );
}
rs0.close();
rs0 = null;
st0.close();
st0 = null;
rs.close();
rs = null;
st.close();
st = null;
conn.close();
conn = null;
try {
System.out.println("Calling commit.........................");
tx2.commit();
}
catch(Exception ex)
{ex.printStackTrace();}
}
catch(Exception e) {
e.printStackTrace();
try {
tx2.rollback();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
%>
<html>
<head>
</head>
<body>
Testing
</body>
</html>
What does your configuration file look like?
Also can you dump the threads when commit hangs.
Riad
We have fixed the problem. Actually a circular list was getting created in this particular scenario. We have fixed TransactionImpl.enlistResource method. Here is the modified method. Can you guys verify it?
==============================
synchronized boolean enlistResource( XAResource xaResource, XAResourceCallback callback )
throws IllegalStateException, SystemException, RollbackException
{
InternalXAResourceHolder resHolder;
InternalXAResourceHolder previousResHolder;
if ( xaResource == null )
throw new IllegalArgumentException( "Argument xaResource is null" );
// Proper notification for transactions that timed out.
if ( _timedOut )
throw new RollbackException( Messages.message( "tyrex.tx.timedOut" ) );
// Check the status of the transaction and act accordingly.
switch ( _status ) {
case STATUS_ACTIVE:
// Transaction is active, we can enlist the resource.
break;
case STATUS_MARKED_ROLLBACK:
// Transaction marked for rollback, we cannot possibly enlist.
throw new RollbackException( Messages.message( "tyrex.tx.markedRollback" ) );
case STATUS_PREPARED:
case STATUS_PREPARING:
case STATUS_COMMITTING:
// Transaction is preparing, cannot enlist resource.
throw new IllegalStateException( Messages.message( "tyrex.tx.inCommit" ) );
case STATUS_ROLLEDBACK:
case STATUS_ROLLING_BACK:
case STATUS_COMMITTED:
case STATUS_NO_TRANSACTION:
case STATUS_UNKNOWN:
default:
throw new IllegalStateException( Messages.message( "tyrex.tx.inactive" ) );
}
if ( _enlisted != null ) {
// Look if we alredy got the resource enlisted. If the
// resource was suspended, we just resume it and go out.
// If the resource was started, we do not enlist it a
// second time.
resHolder = _enlisted;
previousResHolder = null;
while ( resHolder != null ) {
System.out.println("inside enlisted................ while ( resHolder != null )..............");
if ( resHolder._xaResource == xaResource ) {
if ( resHolder._endFlag == XAResource.TMSUSPEND ) {
try {
xaResource.start( resHolder._xid, XAResource.TMRESUME );
resHolder._endFlag = XAResource.TMNOFLAGS;
System.out.println(" ................return true...........................10");
return true;
} catch ( XAException except ) {
except.printStackTrace();
throw new NestedSystemException( except );
} catch ( Exception except ) {
except.printStackTrace();
throw new NestedSystemException( except );
}
} else {
System.out.println("................return false...............................20");
return false;
}
}
previousResHolder = resHolder;
System.out.println("................resHolder = resHolder._nextHolder...............................30");
resHolder = resHolder._nextHolder;
}
// check the delisted
resHolder = _delisted;
InternalXAResourceHolder tmp=null;
while ( resHolder != null ) {
System.out.println("inside delisted................ while ( resHolder != null )..............");
if ( resHolder._xaResource == xaResource ) {
if ( resHolder._endFlag == XAResource.TMSUCCESS ) {
try {
xaResource.start( resHolder._xid, XAResource.TMJOIN );
resHolder._endFlag = XAResource.TMNOFLAGS;
if ( null == previousResHolder ) {
System.out.println("........._delisted = resHolder._nextHolder.................40");
_delisted = resHolder._nextHolder;
_enlisted = resHolder;
} else {
//previousResHolder._nextHolder = resHolder._nextHolder;
if(tmp == null) {
System.out.println("..................... _delisted = _delisted._nextHolder...50");
_delisted = _delisted._nextHolder;
}
else {
System.out.println("........................ tmp._nextHolder = resHolder._nextHolder...55");
tmp._nextHolder = resHolder._nextHolder;
}
/*
if ( null == previousResHolder )
{
_enlisted = resHolder;
resHolder.next = null;
}
else
{
previousResHolder._nextHolder = resHolder;
resHolder.next = null;
}
*/
if ( null == previousResHolder )
{
System.out.println(".................._enlisted = resHolder;...60");
_enlisted = resHolder;
resHolder._nextHolder = null;
}
else
{
System.out.println(".................... resHolder._nextHolder = _enlisted;..70");
//previousResHolder._nextHolder = resHolder;
resHolder._nextHolder = _enlisted;
_enlisted = resHolder;
}
}
/*
if ( null == _enlisted ) {
System.out.println(".. resHolder._nextHolder...........60");
resHolder._nextHolder = null;
}
else {
System.out.println(".. resHolder._nextHolder = _enlisted._nextHolder...........70");
resHolder._nextHolder = _enlisted._nextHolder;
}
_enlisted = resHolder;
*/
return true;
} catch ( Exception except ) {
except.printStackTrace();
throw new NestedSystemException( except );
}
} else {
return false;
}
}
System.out.println("................resHolder = resHolder._nextHolder..............................80");
tmp = resHolder ;
resHolder = resHolder._nextHolder;
}
}
return addNewResource( xaResource, callback );
}
Yes you are correct.
I'll update TransactionImpl.java
when will be new jar available with the patch?
I'm behind on a few patches so I'll say October 6th I'll do a point release with all patches.
Riad