You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2010/10/21 20:12:39 UTC

svn commit: r1026090 - in /cayenne/main/branches/STABLE-3.0: docs/doc/src/main/resources/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ framewor...

Author: aadamchik
Date: Thu Oct 21 18:12:38 2010
New Revision: 1026090

URL: http://svn.apache.org/viewvc?rev=1026090&view=rev
Log:
CAY-1489 NPE using DataContext.objectFromDataRow for a nested context

Patch by Andrei Veprev

Added:
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
Modified:
    cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/NestedDataContextReadTest.java

Modified: cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1026090&r1=1026089&r2=1026090&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt Thu Oct 21 18:12:38 2010
@@ -17,6 +17,7 @@ Bug Fixes Since 3.0.1:
 CAY-1484 Flattened attribute queries are incorrectly generated
 CAY-1485 Memory information for about dialog
 CAY-1488 OutOfMemory when selecting "Remove Foreign Keys Mapped as Object Attributes"
+CAY-1489 NPE using DataContext.objectFromDataRow for a nested context
 CAY-1490 Maven cgen: all and datamap modes can not be activated
 CAY-1496 Problem in derby: comparison operators are not supported on Clob object values. 
 

Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java?rev=1026090&r1=1026089&r2=1026090&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java Thu Oct 21 18:12:38 2010
@@ -594,10 +594,25 @@ public class DataContext extends BaseCon
     public List objectsFromDataRows(
             ClassDescriptor descriptor,
             List<? extends DataRow> dataRows) {
+        // TODO: If data row cache is not available it means that current data context is
+        // child. We need to redirect this method call to parent data context as an
+        // internal query. It is not obvious and has some overhead. Redesign for nested
+        // contexts should be done.
+        if (getObjectStore().getDataRowCache() == null) {
+            return objectsFromDataRowsFromParentContext(descriptor, dataRows);
+        }
         return new ObjectResolver(this, descriptor, true)
                 .synchronizedObjectsFromDataRows(dataRows);
     }
 
+    private List objectsFromDataRowsFromParentContext(
+            ClassDescriptor descriptor,
+            List<? extends DataRow> dataRows) {
+        return getChannel().onQuery(
+                this,
+                new ObjectsFromDataRowsQuery(descriptor, dataRows)).firstList();
+    }
+
     /**
      * Converts a list of DataRows to a List of DataObject registered with this
      * DataContext.

Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java?rev=1026090&r1=1026089&r2=1026090&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java Thu Oct 21 18:12:38 2010
@@ -43,9 +43,28 @@ import org.apache.cayenne.util.ObjectCon
  */
 class DataContextQueryAction extends ObjectContextQueryAction {
 
+    protected DataContext actingDataContext;
+
     public DataContextQueryAction(DataContext actingContext, ObjectContext targetContext,
             Query query) {
         super(actingContext, targetContext, query);
+        actingDataContext = actingContext;
+    }
+
+    @Override
+    protected boolean interceptInternalQuery() {
+        return interceptObjectFromDataRowsQuery();
+    }
+
+    private boolean interceptObjectFromDataRowsQuery() {
+        if (query instanceof ObjectsFromDataRowsQuery) {
+            ObjectsFromDataRowsQuery objectsFromDataRowsQuery = (ObjectsFromDataRowsQuery) query;
+            response = new ListResponse(actingDataContext.objectsFromDataRows(
+                    objectsFromDataRowsQuery.getDescriptor(),
+                    objectsFromDataRowsQuery.getDataRows()));
+            return DONE;
+        }
+        return !DONE;
     }
 
     /**

Added: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java?rev=1026090&view=auto
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java (added)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectsFromDataRowsQuery.java Thu Oct 21 18:12:38 2010
@@ -0,0 +1,158 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.query.PrefetchTreeNode;
+import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.QueryCacheStrategy;
+import org.apache.cayenne.query.QueryMetadata;
+import org.apache.cayenne.query.QueryRouter;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SQLActionVisitor;
+import org.apache.cayenne.reflect.ClassDescriptor;
+
+class ObjectsFromDataRowsQuery implements Query, QueryMetadata {
+
+    private ClassDescriptor descriptor;
+
+    private List<? extends DataRow> dataRows;
+
+    public ObjectsFromDataRowsQuery(ClassDescriptor descriptor,
+            List<? extends DataRow> dataRows) {
+        super();
+        this.descriptor = descriptor;
+        this.dataRows = dataRows;
+    }
+
+    public ClassDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    public List<? extends DataRow> getDataRows() {
+        return dataRows;
+    }
+
+    public QueryMetadata getMetaData(EntityResolver resolver) {
+        return this;
+    }
+
+    public void route(QueryRouter router, EntityResolver resolver, Query substitutedQuery) {
+    }
+
+    public SQLAction createSQLAction(SQLActionVisitor visitor) {
+        return null;
+    }
+
+    public String getName() {
+        return null;
+    }
+
+    public boolean isResolvingInherited() {
+        return false;
+    }
+
+    public int getFetchStartIndex() {
+        return 0;
+    }
+
+    public DataMap getDataMap() {
+        return null;
+    }
+
+    public ClassDescriptor getClassDescriptor() {
+        return null;
+    }
+
+    public ObjEntity getObjEntity() {
+        return null;
+    }
+
+    public DbEntity getDbEntity() {
+        return null;
+    }
+
+    public Procedure getProcedure() {
+        return null;
+    }
+
+    public QueryCacheStrategy getCacheStrategy() {
+        return null;
+    }
+
+    public String getCacheKey() {
+        return null;
+    }
+
+    public String[] getCacheGroups() {
+        return null;
+    }
+
+    public boolean isFetchingDataRows() {
+        return false;
+    }
+
+    public boolean isRefreshingObjects() {
+        return false;
+    }
+
+    public int getPageSize() {
+        return 0;
+    }
+
+    public int getFetchOffset() {
+        return 0;
+    }
+
+    public int getFetchLimit() {
+        return 0;
+    }
+
+    public Query getOrginatingQuery() {
+        return null;
+    }
+
+    public PrefetchTreeNode getPrefetchTree() {
+        return null;
+    }
+
+    public Map<String, String> getPathSplitAliases() {
+        return null;
+    }
+
+    public List<Object> getResultSetMapping() {
+        return null;
+    }
+
+    public int getStatementFetchSize() {
+        return 0;
+    }
+
+    public String getCachePolicy() {
+        return null;
+    }
+}

Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java?rev=1026090&r1=1026089&r2=1026090&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectContextQueryAction.java Thu Oct 21 18:12:38 2010
@@ -88,13 +88,7 @@ public abstract class ObjectContextQuery
             if (interceptRelationshipQuery() != DONE) {
                 if (interceptRefreshQuery() != DONE) {
                     if (interceptLocalCache() != DONE) {
-                        // when changing the flow below, make sure to update
-                        // 'getCacheObjectFactory' method that mimics the interceptors
-                        // below 'interceptLocalCache'. See comment in an inner class
-                        // factory in this method...
-                        if (interceptPaginatedQuery() != DONE) {
-                            runQuery();
-                        }
+                        executePostCache();
                     }
                 }
             }
@@ -104,6 +98,14 @@ public abstract class ObjectContextQuery
         return response;
     }
 
+    private void executePostCache() {
+        if (interceptInternalQuery() != DONE) {
+            if (interceptPaginatedQuery() != DONE) {
+                runQuery();
+            }
+        }
+    }
+
     /**
      * Transfers fetched objects into the target context if it is different from "acting"
      * context. Note that when this method is invoked, result objects are already
@@ -150,6 +152,10 @@ public abstract class ObjectContextQuery
 
     }
 
+    protected boolean interceptInternalQuery() {
+        return !DONE;
+    }
+
     protected boolean interceptOIDQuery() {
         if (query instanceof ObjectIdQuery) {
             ObjectIdQuery oidQuery = (ObjectIdQuery) query;
@@ -315,12 +321,7 @@ public abstract class ObjectContextQuery
         return new QueryCacheEntryFactory() {
 
             public Object createObject() {
-                // must follow the same logic as 'execute' below locla cache interceptor
-                // method... reuse that code somehow???
-                if (interceptPaginatedQuery() != DONE) {
-                    runQuery();
-                }
-
+                executePostCache();
                 return response.firstList();
             }
         };

Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/NestedDataContextReadTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/NestedDataContextReadTest.java?rev=1026090&r1=1026089&r2=1026090&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/NestedDataContextReadTest.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/NestedDataContextReadTest.java Thu Oct 21 18:12:38 2010
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne.access;
 
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 
@@ -26,6 +27,7 @@ import org.apache.art.Artist;
 import org.apache.art.Painting;
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.DataObjectUtils;
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.PersistenceState;
@@ -475,4 +477,24 @@ public class NestedDataContextReadTest e
             unblockQueries();
         }
     }
+
+    public void testObjectFromDataRow() throws Exception {
+        deleteTestData();
+
+        DataContext context = createDataContext();
+        DataContext childContext = (DataContext) context.createChildContext();
+
+        DataRow row = new DataRow(8);
+        row.put("ARTIST_ID", 5l);
+        row.put("ARTIST_NAME", "A");
+        row.put("DATE_OF_BIRTH", new Date());
+
+        Artist artist = childContext.objectFromDataRow(Artist.class, row, true);
+        assertNotNull(artist);
+        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
+        assertSame(childContext, artist.getObjectContext());
+        Object parentArtist = context.getObjectStore().getNode(artist.getObjectId());
+        assertNotNull(parentArtist);
+        assertNotSame(artist, parentArtist);
+    }
 }