You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2004/11/28 00:46:32 UTC

cvs commit: db-ojb/src/java/org/apache/ojb/broker KeyConstraintViolatedException.java

arminw      2004/11/27 15:46:32

  Modified:    src/java/org/apache/ojb/broker/core Tag: OJB_1_0_RELEASE
                        PersistenceBrokerFactorySyncImpl.java
                        PersistenceBrokerHandle.java
               src/java/org/apache/ojb/broker/util/pooling Tag:
                        OJB_1_0_RELEASE ByPassConnection.java
               src/java/org/apache/ojb/broker Tag: OJB_1_0_RELEASE
                        KeyConstraintViolatedException.java
  Log:
  improve exception/tx status handling
  fix problems with abbandoned connections in managed environments
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.7.2.2   +131 -36   db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactorySyncImpl.java
  
  Index: PersistenceBrokerFactorySyncImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactorySyncImpl.java,v
  retrieving revision 1.7.2.1
  retrieving revision 1.7.2.2
  diff -u -r1.7.2.1 -r1.7.2.2
  --- PersistenceBrokerFactorySyncImpl.java	27 Jul 2004 00:33:11 -0000	1.7.2.1
  +++ PersistenceBrokerFactorySyncImpl.java	27 Nov 2004 23:46:32 -0000	1.7.2.2
  @@ -22,9 +22,11 @@
   import javax.transaction.Transaction;
   import javax.transaction.TransactionManager;
   import java.lang.reflect.Field;
  +import java.util.ArrayList;
   import java.util.Collections;
   import java.util.HashMap;
   import java.util.Iterator;
  +import java.util.List;
   import java.util.Map;
   import java.util.WeakHashMap;
   
  @@ -81,7 +83,6 @@
   
       public PersistenceBroker createPersistenceBroker(PBKey pbKey) throws PBFactoryException
       {
  -        PersistenceBroker result = null;
           /*
           try to find a valid PBKey, if given key does not full match
           */
  @@ -105,6 +106,7 @@
               throw new PBFactoryException("Can't create PB instance, failure while lookup" +
                       " running JTA transaction",e);
           }
  +        PersistenceBrokerSyncImpl result = null;
           if (tx != null)
           {
               result = txRegistry.findBroker(tx, pbKey);
  @@ -112,15 +114,17 @@
   
           if(result == null || result.isClosed())
           {
  -            // lookup new PB instance
  -            result = super.createPersistenceBroker(pbKey);
  +            // we have to lookup new PB instance with wrapped with handle
  +            // method #wrapRequestedBrokerInstance wraps the new instance
  +            // with a handle
  +            return super.createPersistenceBroker(pbKey);
           }
           else
           {
  -            // wrap with PB handle
  -            result = super.wrapRequestedBrokerInstance(result);
  +            // we found a PB instance that was already in use within the same JTA-tx
  +            // so we only return a new handle
  +            return new PersistenceBrokerSyncHandle(result);
           }
  -        return result;
       }
   
       protected PersistenceBroker wrapBrokerWithPoolingHandle(PersistenceBroker broker, KeyedObjectPool pool)
  @@ -174,7 +178,7 @@
           {
               throw new PBFactoryException("Error while try to participate in JTA transaction", e);
           }
  -        return super.wrapRequestedBrokerInstance(broker);
  +        return new PersistenceBrokerSyncHandle(pb);
       }
   
       private Transaction searchForValidTx() throws SystemException
  @@ -225,6 +229,10 @@
       public static class PersistenceBrokerSyncImpl extends PoolablePersistenceBroker implements Synchronization
       {
           private Logger log = LoggerFactory.getLogger(PersistenceBrokerSyncImpl.class);
  +        /**
  +         * Used to register all handles using this PB instance
  +         */
  +        private List handleList = new ArrayList();
   
           public PersistenceBrokerSyncImpl(PersistenceBroker broker, KeyedObjectPool pool)
           {
  @@ -234,6 +242,17 @@
           public void beforeCompletion()
           {
               if (log.isDebugEnabled()) log.debug("beforeCompletion was called, nothing to do");
  +            if(handleList.size() > 0)
  +            {
  +                for(int i = 0; i < handleList.size(); i++)
  +                {
  +                    log.warn("Found unclosed PersistenceBroker handle, will do automatic close. Please make" +
  +                            " sure that all used PB instances will be closed.");
  +                    PersistenceBrokerHandle pbh = (PersistenceBrokerHandle) handleList.get(i);
  +                    pbh.close();
  +                }
  +                handleList.clear();
  +            }
               ConnectionManagerIF cm = serviceConnectionManager();
               if(cm.isBatchMode()) cm.executeBatch();
               // close connection immediately when in JTA-tx to avoid bad reports from server con-pool
  @@ -259,7 +278,16 @@
               {
                   if (status != Status.STATUS_COMMITTED)
                   {
  -                    log.error("Abort PB-tx, status of JTA tx is " + getStatusFlagAsString(status));
  +                    if (status == Status.STATUS_ROLLEDBACK || status == Status.STATUS_ROLLING_BACK)
  +                    {
  +                        if (log.isDebugEnabled()) log.debug("Aborting PB-tx due to JTA initiated Rollback: "
  +                                + getStatusFlagAsString(status));
  +                    }
  +                    else
  +                    {
  +                        log.error("Aborting PB-tx due to inconsistent, and unexpected, status of JTA tx: "
  +                                + getStatusFlagAsString(status));
  +                    }
                       internAbort();
                   }
                   else
  @@ -306,39 +334,70 @@
                   if we not in JTA-tx, we close PB instance in a "normal" way. The PB.close()
                   should also release the used connection.
                   */
  -                super.close();
  +                doRealClose();
               }
               else
               {
  -                /*
  -                arminw:
  -                if in JTA-tx, we don't really close the underlying PB instance (return PB
  -                instance to pool, release used connection). As recently as the JTA was
  -                completed we can return PB instance to pool. Thus after tx completion method
  -                doRealClose() was called to close (return to pool) underlying PB instance.
  -
  -                But to free used resources as soon as possible, we release the used connection
  -                immediately. The JTA-tx will handle the connection status in a proper way.
  -                */
  -                if (log.isDebugEnabled())
  -                    log.debug("PB close was called, only close the PB handle when in JTA-tx");
  -                ConnectionManagerIF cm = serviceConnectionManager();
  -                if(cm.isInLocalTransaction())
  +                // if we in tx and other handles operate on the same PB instance, do
  +                // nothing, till all handles are closed.
  +                if(handleList.size() > 0)
                   {
  +                    if(log.isEnabledFor(Logger.INFO)) log.info("PB.close(): Active used by " + handleList.size()
  +                            + " handle objects, will skip close call");
  +                }
  +                else
  +                {
  +                    /*
  +                    arminw:
  +                    if in JTA-tx, we don't really close the underlying PB instance (return PB
  +                    instance to pool, release used connection). As recently as the JTA was
  +                    completed we can return PB instance to pool. Thus after tx completion method
  +                    doRealClose() was called to close (return to pool) underlying PB instance.
  +
  +                    But to free used resources as soon as possible, we release the used connection
  +                    immediately. The JTA-tx will handle the connection status in a proper way.
  +                    */
  +                    if (log.isDebugEnabled())
  +                        log.debug("PB close was called, only close the PB handle when in JTA-tx");
  +
                       /*
  +                    TODO: workaround, in 1.1 use special method do handle this stuff
                       arminw:
  -                    in managed environment this call will be ignored because, the JTA transaction
  -                    manager control the connection status. But to make connectionManager happy we
  -                    have to complete the "local tx" of the connectionManager before release the
  -                    connection
  +                    needed to prevent unclosed connection Statement instances when RsIterator
  +                    wasn't fully materialized in managed environment, because RsIterator is
  +                    a PBStateListener and below we close the connection.
                       */
  -                    cm.localCommit();
  +                    PersistenceBrokerImpl pb = ((PersistenceBrokerImpl) getInnermostDelegate());
  +                    pb.fireBrokerEvent(pb.BEFORE_CLOSE_EVENT);
  +
  +                    ConnectionManagerIF cm = serviceConnectionManager();
  +                    if(cm.isInLocalTransaction())
  +                    {
  +                        /*
  +                        arminw:
  +                        in managed environment con.commit calls will be ignored because, the JTA
  +                        transaction manager control the connection status. But to make
  +                        connectionManager happy we have to complete the "local tx" of the
  +                        connectionManager before release the connection
  +                        */
  +                        cm.localCommit();
  +                    }
  +                    cm.releaseConnection();
                   }
  -                cm.releaseConnection();
               }
               return true;
           }
   
  +        void registerHandle(PersistenceBrokerHandle handle)
  +        {
  +            handleList.add(handle);
  +        }
  +
  +        void deregisterHandle(PersistenceBrokerHandle handle)
  +        {
  +            handleList.remove(handle);
  +        }
  +
           public void beginTransaction() throws TransactionInProgressException, TransactionAbortedException
           {
               throw new UnsupportedOperationException("In managed environments only JTA transaction demarcation allowed");
  @@ -373,12 +432,12 @@
               this.jtaTx = tx;
           }
   
  -        PersistenceBroker find(PBKey key)
  +        PersistenceBrokerSyncImpl find(PBKey key)
           {
  -            return (PersistenceBroker) syncMap.get(key);
  +            return (PersistenceBrokerSyncImpl) syncMap.get(key);
           }
   
  -        void add(PersistenceBroker syncObj)
  +        void add(PersistenceBrokerSyncImpl syncObj)
           {
               if (isLocked)
               {
  @@ -461,7 +520,7 @@
               txBoxMap = Collections.synchronizedMap(new WeakHashMap());
           }
   
  -        void register(Transaction tx, PersistenceBroker syncObject) throws RollbackException, SystemException
  +        void register(Transaction tx, PersistenceBrokerSyncImpl syncObject) throws RollbackException, SystemException
           {
               TransactionBox txBox = (TransactionBox) txBoxMap.get(tx);
               if (txBox == null || txBox.isClosed)
  @@ -475,9 +534,9 @@
               txBox.add(syncObject);
           }
   
  -        PersistenceBroker findBroker(Transaction tx, PBKey pbKey)
  +        PersistenceBrokerSyncImpl findBroker(Transaction tx, PBKey pbKey)
           {
  -            PersistenceBroker result = null;
  +            PersistenceBrokerSyncImpl result = null;
               TransactionBox txBox = (TransactionBox) txBoxMap.get(tx);
               if(txBox != null)
               {
  @@ -494,6 +553,42 @@
           void removeTxBox(Transaction tx)
           {
               txBoxMap.remove(tx);
  +        }
  +    }
  +
  +    //****************************************************
  +    // inner class
  +    //****************************************************
  +    /**
  +     * This wrapper was used when a PB instance which was already in use by a
  +     * transaction was found.
  +     */
  +    class PersistenceBrokerSyncHandle extends PersistenceBrokerHandle
  +    {
  +        /**
  +         * Constructor for the handle, set itself in
  +         * {@link PersistenceBrokerThreadMapping#setCurrentPersistenceBroker}
  +         */
  +        public PersistenceBrokerSyncHandle(PersistenceBrokerSyncImpl broker)
  +        {
  +            super(broker);
  +            // we register handle at underlying PB instance
  +            broker.registerHandle(this);
  +        }
  +
  +        public boolean isClosed()
  +        {
  +            return super.isClosed();
  +        }
  +
  +        public boolean close()
  +        {
  +            if(getDelegate() != null)
  +            {
  +                // deregister from underlying PB instance
  +                ((PersistenceBrokerSyncImpl) getDelegate()).deregisterHandle(this);
  +            }
  +            return super.close();
           }
       }
   }
  
  
  
  1.10.2.1  +2 -2      db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java
  
  Index: PersistenceBrokerHandle.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java,v
  retrieving revision 1.10
  retrieving revision 1.10.2.1
  diff -u -r1.10 -r1.10.2.1
  --- PersistenceBrokerHandle.java	4 Apr 2004 23:53:33 -0000	1.10
  +++ PersistenceBrokerHandle.java	27 Nov 2004 23:46:32 -0000	1.10.2.1
  @@ -17,13 +17,13 @@
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
  -public final class PersistenceBrokerHandle extends DelegatingPersistenceBroker
  +public class PersistenceBrokerHandle extends DelegatingPersistenceBroker
   {
       /**
        * Constructor for the handle, set itself in
        * {@link PersistenceBrokerThreadMapping#setCurrentPersistenceBroker}
        */
  -    public PersistenceBrokerHandle(PersistenceBroker broker)
  +    public PersistenceBrokerHandle(final PersistenceBroker broker)
       {
           super(broker);
           PersistenceBrokerThreadMapping.setCurrentPersistenceBroker(broker.getPBKey(), this);
  
  
  
  No                   revision
  No                   revision
  1.9.2.2   +0 -8      db-ojb/src/java/org/apache/ojb/broker/util/pooling/ByPassConnection.java
  
  Index: ByPassConnection.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/util/pooling/ByPassConnection.java,v
  retrieving revision 1.9.2.1
  retrieving revision 1.9.2.2
  diff -u -r1.9.2.1 -r1.9.2.2
  --- ByPassConnection.java	8 Sep 2004 22:13:00 -0000	1.9.2.1
  +++ ByPassConnection.java	27 Nov 2004 23:46:32 -0000	1.9.2.2
  @@ -64,14 +64,6 @@
       }
   
       /**
  -     * close the wrapped connection
  -     */
  -    public void close() throws SQLException
  -    {
  -        super.close();
  -    }
  -
  -    /**
        * no-op
        */
       public void rollback() throws SQLException
  
  
  
  No                   revision
  No                   revision
  1.5.2.1   +11 -27    db-ojb/src/java/org/apache/ojb/broker/KeyConstraintViolatedException.java
  
  Index: KeyConstraintViolatedException.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/KeyConstraintViolatedException.java,v
  retrieving revision 1.5
  retrieving revision 1.5.2.1
  diff -u -r1.5 -r1.5.2.1
  --- KeyConstraintViolatedException.java	4 Apr 2004 23:53:30 -0000	1.5
  +++ KeyConstraintViolatedException.java	27 Nov 2004 23:46:32 -0000	1.5.2.1
  @@ -1,5 +1,7 @@
   package org.apache.ojb.broker;
   
  +import java.sql.SQLException;
  +
   /* Copyright 2002-2004 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
  @@ -16,48 +18,30 @@
    */
   
   /**
  - * Base class of all exceptions used in OJB.
  + * Exception indicate an SQL key contraint violation.
    *
    * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird<a>
    * @version $Id$
    */
   
  -public class KeyConstraintViolatedException
  -        extends PersistenceBrokerException
  +public class KeyConstraintViolatedException extends PersistenceBrokerSQLException
   {
  -    /**
  -     * Constructor for KeyConstraintViolatedException.
  -     */
       public KeyConstraintViolatedException()
       {
  -        super();
       }
   
  -    /**
  -     * Constructor for KeyConstraintViolatedException.
  -     * @param message
  -     */
  -    public KeyConstraintViolatedException(String message)
  +    public KeyConstraintViolatedException(SQLException t)
       {
  -        super(message);
  +        super(t);
       }
   
  -    /**
  -     * Constructor for KeyConstraintViolatedException.
  -     * @param message
  -     * @param cause
  -     */
  -    public KeyConstraintViolatedException(String message, Throwable cause)
  +    public KeyConstraintViolatedException(String message)
       {
  -        super(message, cause);
  +        super(message);
       }
   
  -    /**
  -     * Constructor for KeyConstraintViolatedException.
  -     * @param cause
  -     */
  -    public KeyConstraintViolatedException(Throwable cause)
  +    public KeyConstraintViolatedException(String message, SQLException t)
       {
  -        super(cause);
  +        super(message, t);
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org