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 ol...@apache.org on 2003/07/27 18:18:16 UTC

cvs commit: db-ojb/src/test/org/apache/ojb/otm OtmExamples.java

olegnitz    2003/07/27 09:18:16

  Modified:    src/java/org/apache/ojb/broker/accesslayer
                        CollectionProxy.java IndirectionHandler.java
               src/java/org/apache/ojb/otm/core ConcreteEditingContext.java
               src/test/org/apache/ojb/otm OtmExamples.java
  Added:       src/java/org/apache/ojb/broker/accesslayer
                        CollectionProxyListener.java
  Log:
  Added CollectionProxyListener for use in OTM:
  now OTM doesn't load all CollectionProxies automatically
  
  Revision  Changes    Path
  1.22      +37 -5     db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionProxy.java
  
  Index: CollectionProxy.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionProxy.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- CollectionProxy.java	19 Jun 2003 11:26:00 -0000	1.21
  +++ CollectionProxy.java	27 Jul 2003 16:18:15 -0000	1.22
  @@ -92,7 +92,9 @@
       */
       private boolean needsClose;
   
  -	public CollectionProxy(PBKey aKey, Query aQuery)
  +    private ArrayList m_listeners;
  +
  +    public CollectionProxy(PBKey aKey, Query aQuery)
   	{
   		this(aKey, RemovalAwareCollection.class, aQuery);
   	}
  @@ -143,8 +145,9 @@
         		else
         		{
         			result = (Collection) getCollectionClass().newInstance();
  -      		}			
  -			return result;			
  +      		}
  +            notifyListeners();
  +			return result;
   		}
   		catch (Exception ex)
   		{
  @@ -156,7 +159,19 @@
   		}
   	}
   
  -	/**
  +    protected void notifyListeners()
  +    {
  +        if (m_listeners != null) 
  +        {
  +            for (int i = m_listeners.size() - 1; i >= 0; i--)
  +            {
  +                CollectionProxyListener l = (CollectionProxyListener) m_listeners.get(i);
  +                l.loaded(this);
  +            }
  +        }
  +    }
  +
  +    /**
   	 * @see Collection#size()
   	 */
   	public int size()
  @@ -457,5 +472,22 @@
   	{
   		this.m_brokerKey = brokerKey;
   	}
  +
  +    public synchronized void addListener(CollectionProxyListener l)
  +    {
  +        if (m_listeners == null)
  +        {
  +            m_listeners = new ArrayList();
  +        }
  +        m_listeners.add(l);
  +    }
  +
  +    public synchronized void removeListener(CollectionProxyListener l)
  +    {
  +        if (m_listeners != null)
  +        {
  +            m_listeners.remove(l);
  +        }
  +    }
   
   }
  
  
  
  1.17      +1 -15     db-ojb/src/java/org/apache/ojb/broker/accesslayer/IndirectionHandler.java
  
  Index: IndirectionHandler.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/IndirectionHandler.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- IndirectionHandler.java	9 Jun 2003 18:50:25 -0000	1.16
  +++ IndirectionHandler.java	27 Jul 2003 16:18:15 -0000	1.17
  @@ -297,14 +297,9 @@
       {
           try
           {
  -            // [oleg] getBroker should go before beforeMaterialization()
  -            // releaseBroker() should go after afterMaterialization()
  -            // because getMaterializingBroker() should return not null for them
  -            PersistenceBroker materializingBroker = getBroker();
  -
               beforeMaterialization();
   
  -            realSubject = materializingBroker.getObjectByIdentity(id);
  +            realSubject = getBroker().getObjectByIdentity(id);
   
               if (realSubject == null)
               {
  @@ -348,13 +343,4 @@
   	{
   		this.brokerKey = brokerKey;
   	}
  -
  -    /**
  -     * This method is for use in MaterializationListeners.
  -     * It allow to use the same broker that was used during the materialization.
  -     */
  -    public PersistenceBroker getMaterializingBroker()
  -    {
  -        return broker;
  -    }
   }
  
  
  
  1.1                  db-ojb/src/java/org/apache/ojb/broker/accesslayer/CollectionProxyListener.java
  
  Index: CollectionProxyListener.java
  ===================================================================
  package org.apache.ojb.broker.accesslayer;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * This is a callback interface that allows interaction with the
   * loading process of the CollectionProxy
   * The OTM layer implements this interface to
   * provide a delayed registration mechanism for ColelctionProxies.
   * @author Oleg Nitz
   * @version $Id: CollectionProxyListener.java,v 1.1 2003/07/27 16:18:15 olegnitz Exp $
   */
  public interface CollectionProxyListener
  {
      /**
       *  this callback is invoked after a CollectionProxy is loaded
       *  @param colProxy the CollectionProxy
       */
      public void loaded(CollectionProxy colProxy);
  }
  
  
  
  1.24      +121 -19   db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java
  
  Index: ConcreteEditingContext.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/core/ConcreteEditingContext.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- ConcreteEditingContext.java	25 Jul 2003 22:49:08 -0000	1.23
  +++ ConcreteEditingContext.java	27 Jul 2003 16:18:16 -0000	1.24
  @@ -79,6 +79,8 @@
   import org.apache.ojb.broker.PBKey;
   import org.apache.ojb.broker.PersistenceBroker;
   import org.apache.ojb.broker.VirtualProxy;
  +import org.apache.ojb.broker.accesslayer.CollectionProxy;
  +import org.apache.ojb.broker.accesslayer.CollectionProxyListener;
   import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
   import org.apache.ojb.broker.accesslayer.IndirectionHandler;
   import org.apache.ojb.broker.accesslayer.MaterializationListener;
  @@ -123,6 +125,7 @@
       private PersistenceBroker _pb;
       private HashMap _original;
       private HashMap _checkpointed;
  +    private HashMap _colProxyListeners;
   
       //////////////////////////////////////////
       // Constructor
  @@ -240,7 +243,7 @@
   
                   if (origObj != null)
                   {
  -                    _original.put(oid, getFields(origObj, false));
  +                    _original.put(oid, getFields(origObj, false, true));
                   }
               }
               _objects.put(oid, entry);
  @@ -348,7 +351,7 @@
           // I think it make sense for efficiency
           _pb.serviceObjectCache().cache(oid, object);
   
  -        _original.put(oid, getFields(object, false));
  +        _original.put(oid, getFields(object, false, true));
   
           // replace the proxy object with the real one
           entry.object = object;
  @@ -381,13 +384,14 @@
        */
       public void commit() throws TransactionAbortedException
       {
  -        checkpointInternal();
  +        checkpointInternal(true);
           releaseLocksAndClear();
       }
   
       private void releaseLocksAndClear()
       {
           releaseLocks();
  +        removeMaterializationListener();
           _objects.clear();
           _order.clear();
           _original.clear();
  @@ -404,13 +408,13 @@
        */
       public void checkpoint() throws TransactionAbortedException
       {
  -        checkpointInternal();
  +        checkpointInternal(false);
           _checkpointed = new HashMap();
           for (Iterator iterator = _order.iterator(); iterator.hasNext();)
           {
               Identity oid = (Identity) iterator.next();
               ContextEntry entry = (ContextEntry) _objects.get(oid);
  -            _checkpointed.put(oid, getFields(entry.object, false));
  +            _checkpointed.put(oid, getFields(entry.object, false, true));
           }
       }
   
  @@ -419,13 +423,16 @@
        *  Writes all changes in this context into the persistent store.
        *
        */
  -    private void checkpointInternal() throws TransactionAbortedException
  +    private void checkpointInternal(boolean isCommit)
  +            throws TransactionAbortedException
       {
           if (_order.size() == 0)
           {
               return;
           }
   
  +        removeCollectionProxyListeners();
  +
           ConnectionManagerIF connMan = _pb.serviceConnectionManager();
           boolean saveBatchMode = connMan.isBatchMode();
           Swizzling swizzlingStrategy = _tx.getKit().getSwizzlingStrategy();
  @@ -474,7 +481,7 @@
                           if (!state.needsDelete())
                           {
                               Object[][] origFields = (Object[][]) _checkpointed.get(oid);
  -                            Object[][] newFields = getFields(entry.object, true);
  +                            Object[][] newFields = getFields(entry.object, true, !isCommit);
   
                               if (origFields == null)
                               {
  @@ -510,10 +517,6 @@
                               }
                           }
                       }
  -                    else
  -                    {
  -                        entry.handler.removeListener(this);
  -                    }
                   }
                   countNewObjects = newObjects.size();
                   if (countNewObjects > 0)
  @@ -662,6 +665,32 @@
               return null;
           }
       }
  +    
  +    private void removeMaterializationListener()
  +    {
  +        for (Iterator it = _order.iterator(); it.hasNext();)
  +        {
  +            Identity oid = (Identity) it.next();
  +            ContextEntry entry = (ContextEntry) _objects.get(oid);
  +            if (entry.handler != null)
  +            {
  +                entry.handler.removeListener(this);
  +            }
  +        }
  +    }
  +
  +    private void removeCollectionProxyListeners()
  +    {
  +        if (_colProxyListeners != null)
  +        {
  +            for (Iterator it = _colProxyListeners.keySet().iterator(); it.hasNext();)
  +            {
  +                CollectionProxyListener listener = (CollectionProxyListener) it.next();
  +                CollectionProxy colProxy = (CollectionProxy) _colProxyListeners.get(listener);
  +                colProxy.removeListener(listener);
  +            }
  +        }
  +    }
   
       /**
        * Read lock all objects reachable via 1:N and N:1 relations
  @@ -699,25 +728,35 @@
   
           // 1:N relations
           Iterator collections = mif.getCollectionDescriptors().iterator();
  -        CollectionDescriptor collectionDescriptor;
  +        CollectionDescriptor cds;
           Object col;
           Iterator colIterator;
  +        PersistentField f;
  +        Class type;
   
           while (collections.hasNext())
           {
  -            collectionDescriptor = (CollectionDescriptor) collections.next();
  -            if (onlyDependants && !collectionDescriptor.getOtmDependent())
  +            cds = (CollectionDescriptor) collections.next();
  +            f = cds.getPersistentField();
  +            type = f.getType();
  +            if (onlyDependants && !cds.getOtmDependent())
               {
                   continue;
               }
  -            col = collectionDescriptor.getPersistentField().get(object);
  +            col = f.get(object);
               if (col != null)
               {
  -                if (col instanceof Collection)
  +                if ((col instanceof CollectionProxy)
  +                        && !((CollectionProxy) col).isLoaded())
  +                {
  +                    continue;
  +                }
  +
  +                if (Collection.class.isAssignableFrom(type))
                   {
                       colIterator = ((Collection) col).iterator();
                   }
  -                else if (col.getClass().isArray())
  +                else if (type.isArray())
                   {
                       colIterator = new ArrayIterator(col);
                   }
  @@ -735,7 +774,7 @@
                       if (_objects.get(relOid) == null)
                       {
                           insertInternal(relOid, relObj, LockType.READ_LOCK, false,
  -                                       collectionDescriptor.getOtmDependent());
  +                                       cds.getOtmDependent());
                       }
                   }
               }
  @@ -796,6 +835,7 @@
       }
   
       /**
  +     * @param addListeners Whether to add CollectionProxy listeners
        * @return four arrays of field values:
        * 1) The class, simple fields, identities of references
        * 2) collections of identities
  @@ -804,7 +844,7 @@
        * if "withObjects" parameter is "false", then returns nulls
        * in places of 3) and 4)
        */
  -    private Object[][] getFields(Object obj, boolean withObjects)
  +    private Object[][] getFields(Object obj, boolean withObjects, boolean addListeners)
       {
           ClassDescriptor mif = _pb.getClassDescriptor(obj.getClass());
           FieldDescriptor[] fieldDescs = mif.getFieldDescriptions();
  @@ -856,6 +896,25 @@
               PersistentField f = cds.getPersistentField();
               Class type = f.getType();
               Object col = f.get(obj);
  +
  +            if ((col != null) && (col instanceof CollectionProxy)
  +                    && !((CollectionProxy) col).isLoaded())
  +            {
  +                if (addListeners)
  +                {
  +                    OTMCollectionProxyListener listener =
  +                            new OTMCollectionProxyListener(cds, collections, count);
  +
  +                    ((CollectionProxy) col).addListener(listener);
  +                    if (_colProxyListeners == null)
  +                    {
  +                        _colProxyListeners = new HashMap();
  +                    }
  +                    _colProxyListeners.put(listener, col);
  +                }
  +                continue;
  +            }
  +
               if (col != null)
               {
                   ArrayList list = new ArrayList();
  @@ -1338,4 +1397,47 @@
           }
       }
   
  +    private class OTMCollectionProxyListener
  +            implements CollectionProxyListener
  +    {
  +
  +        private final CollectionDescriptor _cds;
  +        private final ArrayList[] _collections;
  +        private final int _index;
  +
  +        OTMCollectionProxyListener(CollectionDescriptor cds,
  +                ArrayList[] collections, int index)
  +        {
  +            _cds = cds;
  +            _collections = collections;
  +            _index = index;
  +        }
  +
  +        public void loaded(CollectionProxy colProxy)
  +        {
  +            ArrayList list = new ArrayList();
  +
  +            _collections[_index] = list;
  +
  +            for (Iterator it = colProxy.iterator(); it.hasNext(); )
  +            {
  +                Object relObj = it.next();
  +                Identity relOid = new Identity(relObj, _pb);
  +
  +                list.add(relOid);
  +                if (_objects.get(relOid) == null)
  +                {
  +                    try 
  +                    {
  +                        insertInternal(relOid, relObj, LockType.READ_LOCK, false,
  +                                    _cds.getOtmDependent());
  +                    } 
  +                    catch (LockingException ex)
  +                    {
  +                        throw new LockingPassthruException(ex);
  +                    }
  +                }
  +            }
  +        }
  +    }
   }
  
  
  
  1.14      +76 -0     db-ojb/src/test/org/apache/ojb/otm/OtmExamples.java
  
  Index: OtmExamples.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/otm/OtmExamples.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- OtmExamples.java	28 Jun 2003 12:48:52 -0000	1.13
  +++ OtmExamples.java	27 Jul 2003 16:18:16 -0000	1.14
  @@ -6,8 +6,10 @@
   import org.apache.ojb.broker.Article;
   import org.apache.ojb.broker.InterfaceArticle;
   import org.apache.ojb.broker.ProductGroup;
  +import org.apache.ojb.broker.ProductGroupWithCollectionProxy;
   import org.apache.ojb.broker.Identity;
   import org.apache.ojb.broker.PersistenceBrokerFactory;
  +import org.apache.ojb.broker.accesslayer.CollectionProxy;
   import org.apache.ojb.broker.query.Criteria;
   import org.apache.ojb.broker.query.Query;
   import org.apache.ojb.broker.query.QueryFactory;
  @@ -128,6 +130,80 @@
                   tx.begin();
                   example = (Article) _conn.getObjectByIdentity(oid);
                   _conn.deletePersistent(example);
  +                tx.commit();
  +            }
  +            catch (Throwable ex)
  +            {
  +                ex.printStackTrace();
  +                tx.rollback();
  +            }
  +        }
  +        catch (Throwable ex)
  +        {
  +            try
  +            {
  +                if (tx != null && tx.isInProgress())
  +                {
  +                    tx.rollback();
  +                }
  +            }
  +            catch (Exception ex2)
  +            {
  +            }
  +            throw ex;
  +        }
  +    }
  +
  +    public void testCollectionProxy() throws Throwable
  +    {
  +        Transaction tx = null;
  +
  +        //perform transaction
  +        try
  +        {
  +            tx = _kit.getTransaction(_conn);
  +            tx.begin();
  +
  +            ProductGroupWithCollectionProxy pg = new ProductGroupWithCollectionProxy();
  +            pg.setId(77777);
  +            pg.setName("1");
  +            _conn.makePersistent(pg);
  +
  +            tx.commit();
  +
  +            Identity oid = _conn.getIdentity(pg);
  +
  +            // get from the database
  +            tx = _kit.getTransaction(_conn);
  +            tx.begin();
  +            _conn.invalidate(oid);
  +            pg = (ProductGroupWithCollectionProxy) _conn.getObjectByIdentity(oid);
  +            assertTrue("CollectionProxy isn't loaded",
  +                    !((CollectionProxy) pg.getAllArticlesInGroup()).isLoaded());
  +            Article article = Article.createInstance();
  +            article.setArticleId(77777);
  +            article.setProductGroup(pg);
  +            article.setStock(333);
  +            article.setArticleName("333");
  +            pg.getAllArticlesInGroup().add(article);
  +            _conn.makePersistent(article);
  +            tx.commit();
  +
  +            // get from the database
  +            tx = _kit.getTransaction(_conn);
  +            tx.begin();
  +            _conn.invalidate(oid);
  +            pg = (ProductGroupWithCollectionProxy) _conn.getObjectByIdentity(oid);
  +            assertEquals("CollectionProxy size", 1, pg.getAllArticlesInGroup().size());
  +            tx.commit();
  +
  +            try
  +            {
  +                tx = _kit.getTransaction(_conn);
  +                tx.begin();
  +                pg = (ProductGroupWithCollectionProxy) _conn.getObjectByIdentity(oid);
  +                _conn.deletePersistent(pg.getAllArticlesInGroup().get(0));
  +                _conn.deletePersistent(pg);
                   tx.commit();
               }
               catch (Throwable ex)
  
  
  

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