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.

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.


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 problem
> clearly
> > indicating what is a ManagedConnection and what is a Connection?  From
> your
> > description it looks like perhaps the problem is that we are reusing
> the
> > 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 datasource
> >>from the same transaction. I am not 100% sure about original 
> >>implementation 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

Reply via email to