David Jencks wrote:
I agree that suggested implementation breaks local tx and in this sense is "bad". However, I believe that I can write better implementation that deals with XA connections only. If the plan is to backport 4.0 xa wrapper to 3.2 I would be happy to help with it. If the plan is to ship 3.2 with the old xa wrapper, then we should fix this problem in order to support xa-oracle.I've looked at this in more detail and am 99.9% sure this proposal is a bad idea. I think it will break local tx support.I also think using the 4.0 xa wrapper will solve the problem.
1. I guess the spec says that (theoretically) container can reallocate xa connection from a lower priority task to a higher priority task.Also, the jdbc spec you quote seems to me to effectively prohibit holding a jdbc connection from an xa or pooled driver while you call another ejb: the connection will have been closed when the call returns. Therefore, if you want portable code, you MUST close connections before calling another ejb, and if you do this, the problem you are trying to solve disappears.
2. Specification does not require/imply that the same xa connection should or should not be used for nested ejb call. At the same time is specifically says that only one logical handle can be active at any instant. This means that we can implement any connection management schema as long as it does not violate what is explicitly prohibited. I believe that suggested connection management schema (xa connection is associated with a transation but not allocated for more then one ejb call at a time) is perfectly valid.
If I missed something please enlighten me. thanks david jencks On 2002.11.01 11:29:09 -0500 Igor Fedorenko wrote:Ok, here is the same example with some more details/comments. There was a mistake in my original explanation and I apoligize for confusion.
BeanA allocates a connection
- TxConnectionManager.getManagedConnection allocates
new managed connection mc1 of type
org.jboss.resource.adapter.jdbc.xa.XAManagedConnection which
is a wrapper for (oracle) xa connection xaconn1.
- TxConnectionManager.registerConnectionEventListener(mc1)
creates new TxConnectionEventListener and calls
mc1.addConnectionEventListener
- mc1 gets enlisted into the transaction,
TxConnectionEventListener.enlist is called and mc1 is added
into txToManagedConnectionMap
- mc1.getConnection() is called to get sql connection, it
gets conn1 through xaconn1.getConnection()
BeanA calls BeanB
- nothing special here
BeanB allocates a connection and gets instance conn2 from the same
xaconn1
- TxConnectionManager.getManagedConnection gets mc1 from
txToManagedConnectionMap
- mc1.getConnection() is called to get sql connection, it
gets conn2 through xaconn1.getConnection() and implicitly
invalidates conn1 held by BeanA (see quote below)
BeanB closes the connection and returns
- nothing special
BeanA tries to use the connection
- SQLException("Logical handle no longer valid").
A quote from JDBC 2.0 stdext, section 6.2.3 "Retrieving a Connection":
<quote>
An individual PooledConnection object will usually be asked to produce a series of Connection objects during its lifetime. Only one of these Connection objects may be open at a particular point in time. The connection pooling implementation must call PooledConnection.getConnection() each time a new reference to a pooledConnection is handed out to the JDBC application layer. Each call to PooledConnection.getConnection() must return a newly constructed Connection object that exhibits the default Connection behavior. Only the most recent Connection object produced from a particular PooledConnection is open. An existing Connection object is automatically closed, if the getConnection() method of its associated Pooled-
Connection is called again, before it has been explicitly closed by the application. This gives the application server a way to ‘take away’ a Connection from the application if it wishes, and give it out to someone else. This capability will not likely be used frequently in practice.
</quote>
Attached is a proposed fix. Hope this makes the problem clearer.
David Jencks wrote:
I don't understand. Can you repeat your explanation of the problemclearlyindicating what is a ManagedConnection and what is a Connection? Fromyourdescription it looks like perhaps the problem is that we are reusingthe--java.sql.Connection obtained from a XAConnection? This would not be a problem with the trackConnectionByTx logic but with the xa wrapper. thanks david jencks On 2002.11.01 08:12:05 -0500 Igor Fedorenko wrote:Hi, There is a problem with trackConnectionByTx in the current CVS version of JBoss 3.2 which occurs when two beans access the same datasourcefrom the same transaction. I am not 100% sure about originalimplementation intends and would like to give others an opportunity to complain before I check in updated trackConnectionByTx logic.
Consider the following example
- BeanA allocates a connection and gets an instance conn1
- BeanA calls BeanB
- BeanB allocates a connection and gets the same instance conn1
- BeanB closes the connection and returns
- BeanA tries to use the connection and gets SQLException("Logical
handle is closed").
Updated trackConnectionByTx logic will return the
same connection only if the connection has not been allocated yet
(condition
"BaseConnectionManager2.ConnectionListener.isManagedConnectionFree()");
otherwise allocate and return new connection.
Any objections?
Igor Fedorenko
Think smart. Think automated. Think Dynamics.
www.thinkdynamics.com
Index: TxConnectionManager.java
===================================================================
RCS file: /cvsroot/jboss/jbosscx/src/main/org/jboss/resource/connectionmanager/TxConnectionManager.java,v
retrieving revision 1.2.2.1
diff -u -r1.2.2.1 TxConnectionManager.java
--- TxConnectionManager.java 12 Sep 2002 01:23:46
-0000 1.2.2.1
+++ TxConnectionManager.java 1 Nov 2002 16:06:11 -0000
@@ -13,13 +13,13 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.management.ObjectName;
+
import javax.naming.InitialContext;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
-import javax.resource.spi.ConnectionEventListener;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
@@ -34,8 +34,6 @@
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
-import org.jboss.system.Registry;
-
import org.jboss.logging.Logger;
/**
@@ -129,6 +127,7 @@
private boolean localTransactions;
+ // maps tx => List of connections
private final Map txToManagedConnectionMap = new HashMap();
/**
@@ -261,8 +260,25 @@
ManagedConnection mc = null;
synchronized (txToManagedConnectionMap)
{
- mc = (ManagedConnection)txToManagedConnectionMap.get(tx);
+ List conns = (List) txToManagedConnectionMap.get(tx);
+ if( conns != null )
+ {
+ Iterator i = conns.iterator();
+ while( i.hasNext() )
+ {
+ ManagedConnection conn = (ManagedConnection)
i.next();
+ ConnectionListener listener =
getConnectionEventListener(conn);
+ if( listener != null && listener instanceof
TxConnectionEventListener
+ && ((TxConnectionEventListener)
listener)._isManagedConnectionFree() )
+ {
+ mc = conn;
+ break;
+ }
+ }
+ }
+// mc = (ManagedConnection)txToManagedConnectionMap.get(tx);
}
+ // make sure that connection is not allocated by the client
if (mc != null) {
if (log.isTraceEnabled()) @@ -443,7 +459,13 @@
//Here we actually track the cx by tx.
synchronized(txToManagedConnectionMap)
{
- txToManagedConnectionMap.put(currentTx,
this.getManagedConnection());
+ List conns = (List)
txToManagedConnectionMap.get(currentTx);
+ if( conns == null )
+ {
+ conns = new ArrayList();
+ txToManagedConnectionMap.put(currentTx, conns);
+ }
+ conns.add(this.getManagedConnection());
}
} // end of if ()
@@ -576,7 +598,15 @@
{
synchronized(txToManagedConnectionMap)
{
- txToManagedConnectionMap.remove(currentTx);
+ List conns = (List)
txToManagedConnectionMap.get(currentTx);+ if( conns != null ) + { + conns.remove(ce.getConnectionHandle()); + if( conns.isEmpty() ) + { + txToManagedConnectionMap.remove(currentTx); + } + } } } currentTx = null; @@ -595,6 +625,10 @@ { return false; } // end of if () + return super.isManagedConnectionFree(); + } + boolean _isManagedConnectionFree() + { return super.isManagedConnectionFree(); }------------------------------------------------------- This SF.net email is sponsored by: ApacheCon, November 18-21 in Las Vegas (supported by COMDEX), the only Apache event to be fully supported by the ASF. http://www.apachecon.com _______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development
-- Igor Fedorenko Think smart. Think automated. Think Dynamics. www.thinkdynamics.com ------------------------------------------------------- This SF.net email is sponsored by: ApacheCon, November 18-21 in Las Vegas (supported by COMDEX), the only Apache event to be fully supported by the ASF. http://www.apachecon.com _______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development