FileDocCategorySizeDatePackage
TxConnectionManager.javaAPI DocJBoss 4.2.135948Fri Jul 13 21:01:18 BST 2007org.jboss.resource.connectionmanager

TxConnectionManager

public class TxConnectionManager extends BaseConnectionManager2 implements TxConnectionManagerMBean
The TxConnectionManager is a JBoss ConnectionManager implementation for jca adapters implementing LocalTransaction and XAResource support. It implements a ConnectionEventListener that implements XAResource to manage transactions through the Transaction Manager. To assure that all work in a local transaction occurs over the same ManagedConnection, it includes a xid to ManagedConnection map. When a Connection is requested or a transaction started with a connection handle in use, it checks to see if a ManagedConnection already exists enrolled in the global transaction and uses it if found. Otherwise a free ManagedConnection has its LocalTransaction started and is used. From the BaseConnectionManager2, it includes functionality to obtain managed connections from a ManagedConnectionPool mbean, find the Subject from a SubjectSecurityDomain, and interact with the CachedConnectionManager for connections held over transaction and method boundaries. Important mbean references are to a ManagedConnectionPool supplier (typically a JBossManagedConnectionPool), and a RARDeployment representing the ManagedConnectionFactory. This connection manager has to perform the following operations: 1. When an application component requests a new ConnectionHandle, it must find a ManagedConnection, and make sure a ConnectionEventListener is registered. It must inform the CachedConnectionManager that a connection handle has been given out. It needs to count the number of handles for each ManagedConnection. If there is a current transaction, it must enlist the ManagedConnection's LocalTransaction in the transaction using the ConnectionEventListeners XAResource XAResource implementation. Entry point: ConnectionManager.allocateConnection. written. 2. When a ConnectionClosed event is received from the ConnectionEventListener, it must reduce the handle count. If the handle count is zero, the XAResource should be delisted from the Transaction, if any. The CachedConnectionManager must be notified that the connection is closed. Entry point: ConnectionEventListener.ConnectionClosed. written 3. When a transaction begun notification is received from the UserTransaction (via the CachedConnectionManager, all managedConnections associated with the current object must be enlisted in the transaction. Entry point: (from CachedConnectionManager) ConnectionCacheListener.transactionStarted(Transaction, Collection). The collection is of ConnectionRecord objects. written. 5. When an "entering object" notification is received from the CachedConnectionInterceptor, all the connections for the current object must be associated with a ManagedConnection. if there is a Transaction, the XAResource must be enlisted with it. Entry point: ConnectionCacheListener.reconnect(Collection conns) The Collection is of ConnectionRecord objects. written. 6. When a "leaving object" notification is received from the CachedConnectionInterceptor, all the managedConnections for the current object must have their XAResources delisted from the current Transaction, if any, and cleanup called on each ManagedConnection. Entry point: ConnectionCacheListener.disconnect(Collection conns). written.
author
David Jencks
author
Adrian Brock
version
$Revision: 59870 $

Fields Summary
private static final Throwable
FAILED_TO_ENLIST
private ObjectName
transactionManagerService
private String
tmName
private TransactionManager
tm
private boolean
trackConnectionByTx
private boolean
localTransactions
private int
xaResourceTimeout
private Boolean
isSameRMOverrideValue
Constructors Summary
public TxConnectionManager()
Default managed TxConnectionManager constructor for mbean instances.

   
public TxConnectionManager(CachedConnectionManager ccm, ManagedConnectionPool poolingStrategy, TransactionManager tm)
Creates a new TxConnectionManager instance. for TESTING ONLY!!! not a managed constructor!!

param
ccm a CachedConnectionManager value
param
poolingStrategy a ManagedConnectionPool value
param
tm a TransactionManager value

      super(ccm, poolingStrategy);
      this.tm = tm;
   
Methods Summary
public ConnectionListenercreateConnectionListener(javax.resource.spi.ManagedConnection mc, java.lang.Object context)

      XAResource xaResource = null;
      
      if (localTransactions)
      {
         xaResource = new LocalXAResource(log);
         if (xaResourceTimeout != 0)
            log.debug("XAResource transaction timeout cannot be set for local transactions: " + getJndiName());
      }
      else
      {
         xaResource = JcaXAResourceWrapperFactory.getResourceWrapper(mc.getXAResource(), isSameRMOverrideValue);
         
         if (xaResourceTimeout != 0)
         {
            try
            {
               if (xaResource.setTransactionTimeout(xaResourceTimeout) == false)
                  log.debug("XAResource does not support transaction timeout configuration: " + getJndiName());
            }
            catch (XAException e)
            {
               throw new JBossResourceException("Unable to set XAResource transaction timeout: " + getJndiName(), e);
            }
         }
      }

      ConnectionListener cli = new TxConnectionEventListener(mc, poolingStrategy, context, log, xaResource);
      mc.addConnectionEventListener(cli);
      return cli;
   
public java.lang.BooleangetIsSameRMOverrideValue()

      return isSameRMOverrideValue;
   
public ConnectionListenergetManagedConnection(javax.security.auth.Subject subject, javax.resource.spi.ConnectionRequestInfo cri)

      Transaction trackByTransaction = null;
      try
      {
         Transaction tx = tm.getTransaction();
         if (tx != null && TxUtils.isActive(tx) == false)
            throw new ResourceException("Transaction is not active: tx=" + tx);
         if (trackConnectionByTx)
            trackByTransaction = tx;
      }
      catch (Throwable t)
      {
         JBossResourceException.rethrowAsResourceException("Error checking for a transaction.", t);
      }

      if (trace)
         log.trace("getManagedConnection trackByTx=" + trackConnectionByTx + " tx=" + trackByTransaction);
      return super.getManagedConnection(trackByTransaction, subject, cri);
   
public longgetTimeLeftBeforeTransactionTimeout(boolean errorRollback)

      if (tm == null)
         throw new IllegalStateException("No transaction manager: " + ccmName);
      if (tm instanceof TransactionTimeoutConfiguration)
         return ((TransactionTimeoutConfiguration) tm).getTimeLeftBeforeTransactionTimeout(errorRollback);
      return -1;
   
public java.lang.StringgetTransactionManager()

deprecated

      return this.tmName;
   
public javax.transaction.TransactionManagergetTransactionManagerInstance()

      return tm;
   
public javax.management.ObjectNamegetTransactionManagerService()

      return transactionManagerService;
   
public intgetXAResourceTransactionTimeout()

      return xaResourceTimeout;
   
public booleanisLocalTransactions()

      return localTransactions;
   
public booleanisTrackConnectionByTx()

      return trackConnectionByTx;
   
public booleanisTransactional()

      return TxUtils.isCompleted(tm) == false;
   
protected voidmanagedConnectionDisconnected(ConnectionListener cl)

      Throwable throwable = null;
      try
      {
         cl.delist();
      }
      catch (Throwable t)
      {
         throwable = t;
      }

      //if there are no more handles and tx is complete, we can return to pool.
      boolean isFree = cl.isManagedConnectionFree();
      if (trace)
         log.trace("Disconnected isManagedConnectionFree=" + isFree + " cl=" + cl);
      if (isFree)
         returnManagedConnection(cl, false);

      // Rethrow the error
      if (throwable != null)
         JBossResourceException.rethrowAsResourceException("Could not delist resource, probably a transaction rollback? ", throwable);      
   
protected voidmanagedConnectionReconnected(ConnectionListener cl)

      try
      {
         cl.enlist();
      }
      catch (Throwable t)
      {
         if (trace)
            log.trace("Could not enlist in transaction on entering meta-aware object! " + cl, t);
         throw new JBossResourceException("Could not enlist in transaction on entering meta-aware object!", t);
      }
   
protected static voidrethrowAsSystemException(java.lang.String context, javax.transaction.Transaction tx, java.lang.Throwable t)

   
           
       
   
      if (t instanceof SystemException)
         throw (SystemException) t;
      if (t instanceof RuntimeException)
         throw (RuntimeException) t;
      if (t instanceof Error)
         throw (Error) t;
      if (t instanceof RollbackException)
         throw new IllegalStateException(context + " tx=" + tx + " marked for rollback.");
      throw new NestedRuntimeException(context + " tx=" + tx + " got unexpected error ", t);
   
public voidsetIsSameRMOverrideValue(java.lang.Boolean isSameRMOverride)

      this.isSameRMOverrideValue = isSameRMOverride;
   
public voidsetLocalTransactions(boolean localTransactions)

      this.localTransactions = localTransactions;
   
public voidsetTrackConnectionByTx(boolean trackConnectionByTx)

      this.trackConnectionByTx = trackConnectionByTx;
   
public voidsetTransactionManager(java.lang.String tmName)

deprecated

      this.tmName = tmName;
   
public voidsetTransactionManagerInstance(javax.transaction.TransactionManager tm)

      this.tm = tm;
   
public voidsetTransactionManagerService(javax.management.ObjectName transactionManagerService)

      this.transactionManagerService = transactionManagerService;
   
public voidsetXAResourceTransactionTimeout(int timeout)

      this.xaResourceTimeout = timeout;
   
protected voidstartService()

      if (transactionManagerService != null)
         tm = (TransactionManager)getServer().getAttribute(transactionManagerService, "TransactionManager");
      else
      {
         log.warn("----------------------------------------------------------");
         log.warn("----------------------------------------------------------");
         log.warn("Please change your datasource setup to use <depends optional-attribute-name\"TransactionManagerService\">jboss:service=TransactionManager</depends>");
         log.warn("instead of <attribute name=\"TransactionManager\">java:/TransactionManager</attribute>");
         log.warn("Better still, use a *-ds.xml file");
         log.warn("----------------------------------------------------------");
         log.warn("----------------------------------------------------------");
         tm = (TransactionManager)new InitialContext().lookup(tmName);
      }

      super.startService();
   
protected voidstopService()

      this.tm = null;
      super.stopService();
   
public voidtransactionStarted(java.util.Collection crs)

      Set cls = new HashSet();
      for (Iterator i = crs.iterator(); i.hasNext(); )
      {
         ConnectionRecord cr = (ConnectionRecord)i.next();
         ConnectionListener cl = cr.cl;
         if (!cls.contains(cl))
         {
            cls.add(cl);
            cl.enlist();
         }
      }