This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch past-M2 in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 5e47c4a6de227fe16378733df822a415b47c7c6a Author: Andrus Adamchik <[email protected]> AuthorDate: Sun Jun 14 17:37:39 2026 -0400 cleanup --- .../org/apache/cayenne/access/DataContext.java | 158 ++++++++++++++- .../cayenne/access/DataContextObjectCreator.java | 223 --------------------- .../apache/cayenne/access/DataNodeQueryAction.java | 2 +- .../org/apache/cayenne/access/DataRowStore.java | 6 +- .../apache/cayenne/access/DataRowStoreFactory.java | 4 +- .../org/apache/cayenne/access/DataRowUtils.java | 10 +- .../cayenne/access/DataContextSerializationIT.java | 17 +- 7 files changed, 168 insertions(+), 252 deletions(-) diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java index 7b3298b52..97d81920d 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataContext.java @@ -36,12 +36,15 @@ import org.apache.cayenne.cache.NestedQueryCache; import org.apache.cayenne.cache.QueryCache; import org.apache.cayenne.di.Injector; import org.apache.cayenne.event.EventManager; +import org.apache.cayenne.exp.ValueInjector; +import org.apache.cayenne.graph.ArcId; import org.apache.cayenne.graph.ChildDiffLoader; import org.apache.cayenne.graph.CompoundDiff; import org.apache.cayenne.graph.GraphDiff; import org.apache.cayenne.graph.GraphEvent; import org.apache.cayenne.graph.GraphManager; import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.map.LifecycleEvent; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.query.IteratedQueryDecorator; import org.apache.cayenne.query.MappedExec; @@ -51,8 +54,12 @@ import org.apache.cayenne.query.Query; import org.apache.cayenne.query.QueryMetadata; import org.apache.cayenne.query.RefreshQuery; import org.apache.cayenne.query.Select; +import org.apache.cayenne.reflect.AttributeProperty; import org.apache.cayenne.reflect.ClassDescriptor; import org.apache.cayenne.reflect.PropertyDescriptor; +import org.apache.cayenne.reflect.PropertyVisitor; +import org.apache.cayenne.reflect.ToManyProperty; +import org.apache.cayenne.reflect.ToOneProperty; import org.apache.cayenne.runtime.CayenneRuntime; import org.apache.cayenne.tx.TransactionFactory; import org.apache.cayenne.util.EventUtil; @@ -149,8 +156,6 @@ public class DataContext implements ObjectContext { protected boolean validatingObjectsOnCommit = true; - protected transient DataContextObjectCreator objectCreator; - /** * Creates a new DataContext that is not attached to the Cayenne stack. */ @@ -166,7 +171,6 @@ public class DataContext implements ObjectContext { public DataContext(DataChannel channel, ObjectStore objectStore) { graphAction = new DataContextGraphAction(this); - objectCreator = new DataContextObjectCreator(this); // inject self as parent context if (objectStore != null) { @@ -652,7 +656,17 @@ public class DataContext implements ObjectContext { */ @Override public <T> T newObject(Class<T> persistentClass) { - return objectCreator.newObject(persistentClass); + if (persistentClass == null) { + throw new NullPointerException("Null 'persistentClass'"); + } + + ObjEntity entity = getEntityResolver().getObjEntity(persistentClass); + if (entity == null) { + throw new IllegalArgumentException("Class is not mapped with Cayenne: " + persistentClass.getName()); + } + + + return (T) newObject(entity.getName()); } /** @@ -667,7 +681,27 @@ public class DataContext implements ObjectContext { * @since 3.0 */ public Persistent newObject(String entityName) { - return objectCreator.newObject(entityName); + ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entityName); + if (descriptor == null) { + throw new IllegalArgumentException("Invalid entity name: " + entityName); + } + + Persistent object; + try { + object = (Persistent) descriptor.createObject(); + } catch (Exception ex) { + throw new CayenneRuntimeException("Error instantiating object.", ex); + } + + // this will initialize to-many lists + descriptor.injectValueHolders(object); + + // NOTE: the order of initialization of persistence artifacts below is important - do not change it lightly + object.setObjectId(ObjectId.of(entityName)); + + injectInitialValue(object); + + return object; } /** @@ -682,7 +716,117 @@ public class DataContext implements ObjectContext { */ @Override public void registerNewObject(Object object) { - objectCreator.registerNewObject(object); + if (object == null) { + throw new NullPointerException("Can't register null object."); + } + + ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object); + if (entity == null) { + throw new IllegalArgumentException("Can't find ObjEntity for Persistent class: " + + object.getClass().getName() + ", class is likely not mapped."); + } + + final Persistent persistent = (Persistent) object; + + // sanity check - maybe already registered + if (persistent.getObjectId() != null) { + if (persistent.getObjectContext() == this) { + // already registered, just ignore + return; + } else if (persistent.getObjectContext() != null) { + throw new IllegalStateException("Persistent is already registered with another DataContext. " + + "Try using 'localObjects()' instead."); + } + } else { + persistent.setObjectId(ObjectId.of(entity.getName())); + } + + ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName()); + if (descriptor == null) { + throw new IllegalArgumentException("Invalid entity name: " + entity.getName()); + } + + injectInitialValue(object); + + // now we need to find all arc changes, inject missing value holders and + // pull in all transient connected objects + + descriptor.visitProperties(new PropertyVisitor() { + + public boolean visitToMany(ToManyProperty property) { + property.injectValueHolder(persistent); + + if (!property.isFault(persistent)) { + + Object value = property.readProperty(persistent); + @SuppressWarnings({"unchecked", "rawtypes"}) + Collection<Map.Entry<?, ?>> collection = (value instanceof Map) + ? ((Map) value).entrySet() + : (Collection<Map.Entry<?, ?>>) value; + + for (Object target : collection) { + if (target instanceof Persistent targetDO) { + // make sure it is registered + registerNewObject(targetDO); + getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property)); + } + } + } + return true; + } + + public boolean visitToOne(ToOneProperty property) { + Object target = property.readPropertyDirectly(persistent); + + if (target instanceof Persistent targetDO) { + // make sure it is registered + registerNewObject(targetDO); + getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property)); + } + return true; + } + + public boolean visitAttribute(AttributeProperty property) { + return true; + } + }); + } + + /** + * If ObjEntity qualifier is set, asks it to inject initial value to an object. + * Also performs all Persistent initialization operations + */ + private void injectInitialValue(Object obj) { + // must follow this exact order of property initialization per CAY-653, + // i.e. have the id and the context in place BEFORE setPersistence is called + + Persistent object = (Persistent) obj; + + object.setObjectContext(this); + object.setPersistenceState(PersistenceState.NEW); + + GraphManager graphManager = getGraphManager(); + synchronized (graphManager) { + graphManager.registerNode(object.getObjectId(), object); + graphManager.nodeCreated(object.getObjectId()); + } + + ObjEntity entity; + try { + entity = getEntityResolver().getObjEntity(object.getObjectId().getEntityName()); + } catch (CayenneRuntimeException ex) { + // ObjEntity cannot be fetched, ignored + entity = null; + } + + if (entity != null) { + if (entity.getDeclaredQualifier() instanceof ValueInjector valueInjector) { + valueInjector.injectValue(object); + } + } + + // invoke callbacks + getEntityResolver().getCallbackRegistry().performCallbacks(LifecycleEvent.POST_ADD, object); } /** @@ -1180,8 +1324,6 @@ public class DataContext implements ObjectContext { } } - objectCreator = new DataContextObjectCreator(this); - // ... deferring initialization of transient properties of this context till first access, // so that it can attach to Cayenne runtime using appropriate thread injector. } diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataContextObjectCreator.java b/cayenne/src/main/java/org/apache/cayenne/access/DataContextObjectCreator.java deleted file mode 100644 index 9b03889f1..000000000 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataContextObjectCreator.java +++ /dev/null @@ -1,223 +0,0 @@ -/***************************************************************** - * 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 - * - * https://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 org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.ObjectId; -import org.apache.cayenne.PersistenceState; -import org.apache.cayenne.Persistent; -import org.apache.cayenne.exp.ValueInjector; -import org.apache.cayenne.graph.ArcId; -import org.apache.cayenne.graph.GraphManager; -import org.apache.cayenne.map.LifecycleEvent; -import org.apache.cayenne.map.ObjEntity; -import org.apache.cayenne.reflect.AttributeProperty; -import org.apache.cayenne.reflect.ClassDescriptor; -import org.apache.cayenne.reflect.PropertyVisitor; -import org.apache.cayenne.reflect.ToManyProperty; -import org.apache.cayenne.reflect.ToOneProperty; - -import java.util.Collection; -import java.util.Map; - -/** - * {@link DataContext} delegates creation and registration of new objects to this class - */ -class DataContextObjectCreator { - - final DataContext context; - - DataContextObjectCreator(DataContext context) { - this.context = context; - } - - /** - * Create new object for the given persistent class - * - * @param persistentClass to create object from - * @return a new persistent object - * @param <T> type of the object - * @see DataContext#newObject(Class) - */ - <T> T newObject(Class<T> persistentClass) { - if (persistentClass == null) { - throw new NullPointerException("Null 'persistentClass'"); - } - - ObjEntity entity = context.getEntityResolver().getObjEntity(persistentClass); - if (entity == null) { - throw new IllegalArgumentException("Class is not mapped with Cayenne: " + persistentClass.getName()); - } - - @SuppressWarnings("unchecked") - T object = (T) newObject(entity.getName()); - return object; - } - - /** - * Create new object for the given entity name - * @param entityName name of the ObjEntity - * @return a new persistent object - * @see DataContext#newObject(String) - */ - Persistent newObject(String entityName) { - ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(entityName); - if (descriptor == null) { - throw new IllegalArgumentException("Invalid entity name: " + entityName); - } - - Persistent object; - try { - object = (Persistent) descriptor.createObject(); - } catch (Exception ex) { - throw new CayenneRuntimeException("Error instantiating object.", ex); - } - - // this will initialize to-many lists - descriptor.injectValueHolders(object); - - // NOTE: the order of initialization of persistence artifacts below is important - do not change it lightly - object.setObjectId(ObjectId.of(entityName)); - - injectInitialValue(object); - - return object; - } - - /** - * Register new object created outside the context - * @param object to register - * @see DataContext#registerNewObject(Object) - */ - void registerNewObject(Object object) { - if (object == null) { - throw new NullPointerException("Can't register null object."); - } - - ObjEntity entity = context.getEntityResolver().getObjEntity((Persistent) object); - if (entity == null) { - throw new IllegalArgumentException("Can't find ObjEntity for Persistent class: " - + object.getClass().getName() + ", class is likely not mapped."); - } - - final Persistent persistent = (Persistent) object; - - // sanity check - maybe already registered - if (persistent.getObjectId() != null) { - if (persistent.getObjectContext() == context) { - // already registered, just ignore - return; - } else if (persistent.getObjectContext() != null) { - throw new IllegalStateException("Persistent is already registered with another DataContext. " - + "Try using 'localObjects()' instead."); - } - } else { - persistent.setObjectId(ObjectId.of(entity.getName())); - } - - ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(entity.getName()); - if (descriptor == null) { - throw new IllegalArgumentException("Invalid entity name: " + entity.getName()); - } - - injectInitialValue(object); - - // now we need to find all arc changes, inject missing value holders and - // pull in all transient connected objects - - descriptor.visitProperties(new PropertyVisitor() { - - public boolean visitToMany(ToManyProperty property) { - property.injectValueHolder(persistent); - - if (!property.isFault(persistent)) { - - Object value = property.readProperty(persistent); - @SuppressWarnings({"unchecked", "rawtypes"}) - Collection<Map.Entry<?,?>> collection = (value instanceof Map) - ? ((Map) value).entrySet() - : (Collection<Map.Entry<?, ?>>) value; - - for (Object target : collection) { - if (target instanceof Persistent targetDO) { - // make sure it is registered - registerNewObject(targetDO); - context.getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property)); - } - } - } - return true; - } - - public boolean visitToOne(ToOneProperty property) { - Object target = property.readPropertyDirectly(persistent); - - if (target instanceof Persistent targetDO) { - // make sure it is registered - registerNewObject(targetDO); - context.getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property)); - } - return true; - } - - public boolean visitAttribute(AttributeProperty property) { - return true; - } - }); - } - - /** - * If ObjEntity qualifier is set, asks it to inject initial value to an object. - * Also performs all Persistent initialization operations - */ - protected void injectInitialValue(Object obj) { - // must follow this exact order of property initialization per CAY-653, - // i.e. have the id and the context in place BEFORE setPersistence is called - - Persistent object = (Persistent) obj; - - object.setObjectContext(context); - object.setPersistenceState(PersistenceState.NEW); - - GraphManager graphManager = context.getGraphManager(); - synchronized (graphManager) { - graphManager.registerNode(object.getObjectId(), object); - graphManager.nodeCreated(object.getObjectId()); - } - - ObjEntity entity; - try { - entity = context.getEntityResolver().getObjEntity(object.getObjectId().getEntityName()); - } catch (CayenneRuntimeException ex) { - // ObjEntity cannot be fetched, ignored - entity = null; - } - - if (entity != null) { - if (entity.getDeclaredQualifier() instanceof ValueInjector valueInjector) { - valueInjector.injectValue(object); - } - } - - // invoke callbacks - context.getEntityResolver() - .getCallbackRegistry().performCallbacks(LifecycleEvent.POST_ADD, object); - } -} diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataNodeQueryAction.java b/cayenne/src/main/java/org/apache/cayenne/access/DataNodeQueryAction.java index a071a92c6..077ca5b51 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataNodeQueryAction.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataNodeQueryAction.java @@ -66,7 +66,7 @@ class DataNodeQueryAction { } @Override - public void nextRows(Query q, ResultIterator it) { + public void nextRows(Query q, ResultIterator<?> it) { observer.nextRows(originalQuery, it); } diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataRowStore.java b/cayenne/src/main/java/org/apache/cayenne/access/DataRowStore.java index 992f6beba..18cd4d065 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataRowStore.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataRowStore.java @@ -55,7 +55,11 @@ public class DataRowStore implements Serializable { // default property values - public static final long SNAPSHOT_EXPIRATION_DEFAULT = 2 * 60 * 60; // default expiration time is 2 hours + /** + * @deprecated unused + */ + @Deprecated(since = "5.0", forRemoval = true) + public static final long SNAPSHOT_EXPIRATION_DEFAULT = 2 * 60 * 60; public static final int SNAPSHOT_CACHE_SIZE_DEFAULT = 10000; protected String name; diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataRowStoreFactory.java b/cayenne/src/main/java/org/apache/cayenne/access/DataRowStoreFactory.java index f212fdfa2..fd5a6e926 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataRowStoreFactory.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataRowStoreFactory.java @@ -29,9 +29,7 @@ public interface DataRowStoreFactory { /** * Create new {@link DataRowStore} object. * - * @since 4.0 - * @param name DataRowStore name. Used to identify this DataRowStore in events, etc. - * Can't be null. + * @param name DataRowStore name. Used to identify this DataRowStore in events, etc. Can't be null. */ DataRowStore createDataRowStore(String name); diff --git a/cayenne/src/main/java/org/apache/cayenne/access/DataRowUtils.java b/cayenne/src/main/java/org/apache/cayenne/access/DataRowUtils.java index eac6c1bcc..aad3ff7db 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/DataRowUtils.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/DataRowUtils.java @@ -19,13 +19,10 @@ package org.apache.cayenne.access; -import java.util.Map; - import org.apache.cayenne.DataRow; import org.apache.cayenne.ObjectId; import org.apache.cayenne.PersistenceState; import org.apache.cayenne.Persistent; -import org.apache.cayenne.exp.path.CayennePath; import org.apache.cayenne.map.DbJoin; import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.ObjAttribute; @@ -37,6 +34,8 @@ import org.apache.cayenne.reflect.PropertyVisitor; import org.apache.cayenne.reflect.ToManyProperty; import org.apache.cayenne.reflect.ToOneProperty; +import java.util.Map; + /** * DataRowUtils contains a number of static methods to work with DataRows. This is a * helper class for DataContext and ObjectStore. @@ -137,6 +136,7 @@ class DataRowUtils { descriptor.visitProperties(new PropertyVisitor() { + @Override public boolean visitAttribute(AttributeProperty property) { String dbAttrPath = property.getAttribute().getDbAttributePath().value(); @@ -159,11 +159,13 @@ class DataRowUtils { return true; } + @Override public boolean visitToMany(ToManyProperty property) { // noop - nothing to merge return true; } + @Override public boolean visitToOne(ToOneProperty property) { ObjRelationship relationship = property.getRelationship(); if (relationship.isToPK()) { @@ -174,7 +176,7 @@ class DataRowUtils { DbRelationship dbRelationship = relationship .getDbRelationships() - .get(0); + .getFirst(); // must check before creating ObjectId because of partial snapshots if (hasFK(dbRelationship, snapshot)) { diff --git a/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java b/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java index e52d25fb4..15506eb36 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/DataContextSerializationIT.java @@ -82,22 +82,22 @@ public class DataContextSerializationIT { } @Test - public void serializeChannel() throws Exception { + public void serializeParent() throws Exception { DataContext deserializedContext = Util.cloneViaSerialization(context); - assertNotNull(deserializedContext.getChannel()); - assertSame(context.getChannel(), deserializedContext.getChannel()); + assertNotNull(deserializedContext.getParent()); + assertSame(context.getParent(), deserializedContext.getParent()); } @Test - public void serializeNestedChannel() throws Exception { + public void serializeNestedParent() throws Exception { ObjectContext child = runtime.newContext(context); ObjectContext deserializedContext = Util.cloneViaSerialization(child); - assertNotNull(deserializedContext.getChannel()); + assertNotNull(deserializedContext.getParent()); assertNotNull(deserializedContext.getEntityResolver()); } @@ -267,11 +267,4 @@ public class DataContextSerializationIT { assertEquals("artist2", deserializedArtist.getArtistName()); assertSame(deserializedContext, deserializedArtist.getObjectContext()); } - - @Test - public void serializeObjectCreator() throws Exception { - DataContext deserializedContext = Util.cloneViaSerialization(context); - assertNotNull(deserializedContext.objectCreator); - assertSame(deserializedContext, deserializedContext.objectCreator.context); - } }
