arminw      2005/09/27 17:30:23

  Modified:    src/java/org/apache/ojb/broker/core/proxy Tag:
                        OJB_1_0_RELEASE AbstractIndirectionHandler.java
  Log:
  use inner class to handle temporary used PB instances to avoid concurrency 
issues
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.1.2.4   +88 -74    
db-ojb/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java
  
  Index: AbstractIndirectionHandler.java
  ===================================================================
  RCS file: 
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java,v
  retrieving revision 1.1.2.3
  retrieving revision 1.1.2.4
  diff -u -r1.1.2.3 -r1.1.2.4
  --- AbstractIndirectionHandler.java   26 Sep 2005 23:57:44 -0000      1.1.2.3
  +++ AbstractIndirectionHandler.java   28 Sep 2005 00:30:23 -0000      1.1.2.4
  @@ -30,15 +30,13 @@
   
   /**
    * Abstract implementation for the indirection handler used by ojb's proxies.
  - * 
  + *
    * @version $Id$
    */
   public abstract class AbstractIndirectionHandler implements 
IndirectionHandler
   {
       static final long serialVersionUID = -1993879565033755826L;
  -    
  -     /** Reference to the used PersistenceBroker */
  -    private transient PersistenceBrokerInternal _broker = null;
  +
       /** The key for acquiring the above broker */
       private PBKey _brokerKey;
       /** The real subject which this is hidden by the proxy */
  @@ -51,7 +49,7 @@
   
        /**
         * Creates a new indirection handler for the indicated object.
  -      * 
  +      *
         * @param brokerKey
         *            The key of the persistence broker
         * @param id
  @@ -65,7 +63,7 @@
   
        /**
         * Returns the identity of the subject.
  -      * 
  +      *
         * @return The identity
         */
        public Identity getIdentity()
  @@ -75,7 +73,7 @@
   
        /**
         * Sets the identity of the subject of this indirection handler.
  -      * 
  +      *
         * @param identity
         */
        protected void setIdentity(Identity identity)
  @@ -86,7 +84,7 @@
        /**
         * Returns the key of the persistence broker used by this indirection
         * handler.
  -      * 
  +      *
         * @return The broker key
         */
        public PBKey getBrokerKey()
  @@ -96,7 +94,7 @@
   
        /**
         * Sets the key of the persistence broker used by this indirection 
handler.
  -      * 
  +      *
         * @param brokerKey
         *            The broker key
         */
  @@ -107,7 +105,7 @@
   
        /**
         * Adds a materialization listener.
  -      * 
  +      *
         * @param listener
         *            The listener to add
         */
  @@ -126,7 +124,7 @@
   
        /**
         * Removes a materialization listener.
  -      * 
  +      *
         * @param listener
         *            The listener to remove
         */
  @@ -179,65 +177,48 @@
                }
        }
   
  -     /**
  -      * Gets the persistence broker used by this indirection handler. If no 
PBKey
  -      * is available a runtime exception will be thrown.
  -      * 
  -      * @return a PersistenceBroker
  -      */
  -     protected synchronized PersistenceBrokerInternal getBroker() throws 
PBFactoryException
  -     {
  -             PersistenceBrokerInternal broker;
  -
  -             if (getBrokerKey() == null)
  -             {
  -                     /*
  -                      * arminw: if no PBKey is set we throw an exception, 
because we
  -                      * don't know which PB (connection) should be used.
  -                      */
  -                     throw new OJBRuntimeException("Can't find associated 
PBKey. Need PBKey to obtain a valid"
  -                                     + "PersistenceBroker instance from 
intern resources.");
  -             }
  -             // first try to use the current threaded broker to avoid 
blocking
  -             broker = 
PersistenceBrokerThreadMapping.currentPersistenceBroker(getBrokerKey());
  -             // current broker not found, create a intern new one
  -             if (broker == null)
  -             {
  -                     if (_broker == null)
  -                     {
  -                             _broker = (PersistenceBrokerInternal) 
PersistenceBrokerFactory.createPersistenceBroker(getBrokerKey());
  -                     }
  -            broker = _broker;
  +    /**
  +     * Gets the persistence broker used by this indirection handler.
  +     * If no PBKey is available a runtime exception will be thrown.
  +     *
  +     * @return a PersistenceBroker
  +     */
  +    protected TemporaryBrokerWrapper getBroker() throws PBFactoryException
  +    {
  +        PersistenceBrokerInternal broker;
  +        boolean needsClose = false;
  +
  +        if (getBrokerKey() == null)
  +        {
  +            /*
  +            arminw:
  +            if no PBKey is set we throw an exception, because we don't
  +            know which PB (connection) should be used.
  +            */
  +            throw new OJBRuntimeException("Can't find associated PBKey. Need 
PBKey to obtain a valid" +
  +                                          "PersistenceBroker instance from 
intern resources.");
           }
  -             return broker;
  -     }
  -
  -     /**
  -      * Release the PersistenceBroker instance currently used.
  -      */
  -     protected void releaseBroker()
  -     {
  -             /*
  -        arminw:
  -        only close broker instance if we get it from PBF, this
  -        is the case when _broker is not null
  -        */
  -        if (_broker != null)
  -             {
  -                     if(!_broker.isClosed()) _broker.close();
  -                     _broker = null;
  -             }
  -     }
  +        // first try to use the current threaded broker to avoid blocking
  +        broker = 
PersistenceBrokerThreadMapping.currentPersistenceBroker(getBrokerKey());
  +        // current broker not found, create a intern new one
  +        if ((broker == null) || broker.isClosed())
  +        {
  +            broker = (PersistenceBrokerInternal) 
PersistenceBrokerFactory.createPersistenceBroker(getBrokerKey());
  +            /** Specifies whether we obtained a fresh broker which we have 
to close after we used it */
  +            needsClose = true;
  +        }
  +        return new TemporaryBrokerWrapper(broker, needsClose);
  +    }
   
        /**
         * [Copied from [EMAIL PROTECTED] 
java.lang.reflect.InvocationHandler}]:<br/>
         * Processes a method invocation on a proxy instance and returns the 
result.
         * This method will be invoked on an invocation handler when a method is
         * invoked on a proxy instance that it is associated with.
  -      * 
  +      *
         * @param proxy
         *            The proxy instance that the method was invoked on
  -      * 
  +      *
         * @param method
         *            The <code>Method</code> instance corresponding to the
         *            interface method invoked on the proxy instance. The 
declaring
  @@ -245,7 +226,7 @@
         *            interface that the method was declared in, which may be a
         *            superinterface of the proxy interface that the proxy class
         *            inherits the method through.
  -      * 
  +      *
         * @param args
         *            An array of objects containing the values of the arguments
         *            passed in the method invocation on the proxy instance, or
  @@ -254,7 +235,7 @@
         *            appropriate primitive wrapper class, such as
         *            <code>java.lang.Integer</code> or
         *            <code>java.lang.Boolean</code>.
  -      * 
  +      *
         * @return The value to return from the method invocation on the proxy
         *         instance. If the declared return type of the interface 
method is
         *         a primitive type, then the value returned by this method 
must be
  @@ -268,7 +249,7 @@
         *         declared return type as described above, a
         *         <code>ClassCastException</code> will be thrown by the method
         *         invocation on the proxy instance.
  -      * 
  +      *
         * @throws PersistenceBrokerException
         *             The exception to throw from the method invocation on the
         *             proxy instance. The exception's type must be assignable
  @@ -283,7 +264,7 @@
         *             [EMAIL PROTECTED] 
java.lang.reflect.UndeclaredThrowableException}
         *             containing the exception that was thrown by this method 
will
         *             be thrown by the method invocation on the proxy instance.
  -      * 
  +      *
         * @see java.lang.reflect.UndeclaredThrowableException
         */
        public Object invoke(Object proxy, Method method, Object[] args)
  @@ -352,13 +333,14 @@
                        // otherwise equals may return false.
                        if ("equals".equals(methodName) && args[0] != null)
                        {
  +                TemporaryBrokerWrapper tmp = getBroker();
                   try
                   {
  -                    args[0] = 
getBroker().getProxyFactory().getRealObject(args[0]);
  +                    args[0] = 
tmp.broker.getProxyFactory().getRealObject(args[0]);
                   }
                   finally
                   {
  -                    releaseBroker();
  +                    tmp.close();
                   }
               }
   
  @@ -385,7 +367,7 @@
        /**
         * Returns the proxies real subject. The subject will be materialized if
         * necessary.
  -      * 
  +      *
         * @return The subject
         */
        public Object getRealSubject() throws PersistenceBrokerException
  @@ -412,14 +394,15 @@
        /**
         * Retrieves the real subject from the underlying RDBMS. Override this
         * method if the object is to be materialized in a specific way.
  -      * 
  +      *
         * @return The real subject of the proxy
         */
        protected synchronized Object materializeSubject() throws 
PersistenceBrokerException
        {
  -             try
  +             TemporaryBrokerWrapper tmp = getBroker();
  +        try
                {
  -                     Object realSubject = 
getBroker().getObjectByIdentity(_id);
  +                     Object realSubject = 
tmp.broker.getObjectByIdentity(_id);
                        if (realSubject == null)
                        {
                                
LoggerFactory.getLogger(IndirectionHandler.class).warn(
  @@ -431,13 +414,13 @@
                        throw new PersistenceBrokerException(ex);
                } finally
                {
  -                     releaseBroker();
  +                     tmp.close();
                }
        }
   
        /**
         * Determines whether the real subject already has been materialized.
  -      * 
  +      *
         * @return <code>true</code> if the real subject has already been loaded
         */
        public boolean alreadyMaterialized()
  @@ -448,10 +431,41 @@
        /**
         * Generate a simple object that is serializable and placeholder for
         * proxies.
  -      * 
  +      *
         */
        private Object generateSerializableProxy()
        {
                return new 
OJBSerializableProxy(getIdentity().getObjectsRealClass(), this);
        }
  +
  +    //===================================================================
  +    // inner class
  +    //===================================================================
  +    /**
  +     * wrapper class for temporary used broker instances.
  +     */
  +    static final class TemporaryBrokerWrapper
  +    {
  +        /** Specifies whether we obtained a fresh broker which we have to 
close after we used it */
  +        boolean needsClose;
  +        PersistenceBrokerInternal broker;
  +
  +        public TemporaryBrokerWrapper(PersistenceBrokerInternal broker, 
boolean needsClose)
  +        {
  +            this.broker = broker;
  +            this.needsClose = needsClose;
  +        }
  +
  +        /**
  +         * Cleanup the used broker instance, it's mandatory to call
  +         * this method after use.
  +         */
  +        public void close()
  +        {
  +            if(needsClose)
  +            {
  +                broker.close();
  +            }
  +        }
  +    }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to