You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/09/04 20:25:43 UTC
[isis] 01/24: ISIS-1976: add layer of abstraction as first step to
deprecate ObjectAdapter caching
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch ISIS-1976-rethink-object-adapters
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 9d64857d5b9da761725147e4d3a411288e37c737
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Sep 1 12:02:32 2018 +0200
ISIS-1976: add layer of abstraction as first step to deprecate
ObjectAdapter caching
Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
.../system/persistence/PersistenceSession4.java | 182 +++-------------
.../system/persistence/PersistenceSession5.java | 193 +++--------------
.../adaptermanager/ObjectAdapterLegacy.java | 234 +++++++++++++++++++++
.../adaptermanager/OidAdapterHashMap.java | 4 +-
.../adaptermanager/PojoAdapterHashMap.java | 6 +-
5 files changed, 292 insertions(+), 327 deletions(-)
diff --git a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java b/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
index 3f99a1a..fe9d89f 100644
--- a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
+++ b/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
@@ -59,7 +59,6 @@ import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.ensure.Assert;
-import org.apache.isis.core.commons.ensure.IsisAssertException;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.factory.InstanceUtil;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -69,7 +68,6 @@ import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
import org.apache.isis.core.metamodel.adapter.version.Version;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.facets.actcoll.typeof.ElementSpecificationProviderFromTypeOfFacet;
import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
@@ -91,7 +89,6 @@ import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingCallbackFa
import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacet;
import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
-import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
import org.apache.isis.core.metamodel.services.ServicesInjector;
import org.apache.isis.core.metamodel.services.container.query.QueryCardinality;
import org.apache.isis.core.metamodel.spec.FreeStandingList;
@@ -113,9 +110,8 @@ import org.apache.isis.core.runtime.persistence.objectstore.transaction.Persiste
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
import org.apache.isis.core.runtime.services.RequestScopedService;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.OidAdapterHashMap;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.PojoAdapterHashMap;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.RootAndCollectionAdapters;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy.ObjectAdapterContext;
import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
@@ -136,6 +132,7 @@ public class PersistenceSession4 extends PersistenceSessionBase
implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession4.class);
+ private ObjectAdapterContext objectAdapterContext;
/**
* Initialize the object store so that calls to this object store access
@@ -164,8 +161,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
LOG.debug("opening {}", this);
}
- oidAdapterMap.open();
- pojoAdapterMap.open();
+ objectAdapterContext = ObjectAdapterLegacy.openContext(servicesInjector);
persistenceManager = jdoPersistenceManagerFactory.getPersistenceManager();
@@ -233,7 +229,10 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
/**
* Creates {@link ObjectAdapter adapters} for the service list, ensuring that these are mapped correctly,
* and have the same OIDs as in any previous sessions.
+ *
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
*/
+ @Deprecated
private void initServices() {
final List<Object> registeredServices = servicesInjector.getRegisteredServices();
for (final Object service : registeredServices) {
@@ -244,7 +243,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void remapAsPersistentIfRequired(final ObjectAdapter serviceAdapter) {
if (serviceAdapter.getOid().isTransient()) {
- remapAsPersistent(serviceAdapter, null);
+ objectAdapterContext.remapAsPersistent(serviceAdapter, null, this);
}
}
@@ -310,19 +309,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
"close: failed to close JDO persistenceManager; continuing to avoid memory leakage");
}
- try {
- oidAdapterMap.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
- }
-
- try {
- pojoAdapterMap.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: pojoAdapterMap#close() failed; continuing to avoid memory leakage");
- }
+ objectAdapterContext.close();
this.state = State.CLOSED;
}
@@ -1123,14 +1110,11 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
// -- AdapterManager implementation
- private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
- private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
-
@Override
public ObjectAdapter getAdapterFor(final Object pojo) {
Objects.requireNonNull(pojo);
- return pojoAdapterMap.getAdapter(pojo);
+ return objectAdapterContext.lookupPojoAdapter(pojo);
}
@Override
@@ -1138,7 +1122,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
Objects.requireNonNull(oid);
ensureMapsConsistent(oid);
- return oidAdapterMap.getAdapter(oid);
+ return objectAdapterContext.lookupOidAdapter(oid);
}
@@ -1194,11 +1178,13 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
/**
* Fail early if any problems.
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
*/
+ @Deprecated
private void ensureMapsConsistent(final Oid oid) {
Objects.requireNonNull(oid);
- final ObjectAdapter adapter = oidAdapterMap.getAdapter(oid);
+ final ObjectAdapter adapter = objectAdapterContext.lookupOidAdapter(oid);
if (adapter == null) {
return;
}
@@ -1208,7 +1194,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void ensurePojoAdapterMapConsistent(final ObjectAdapter adapter) {
final Object adapterPojo = adapter.getObject();
- final ObjectAdapter adapterAccordingToMap = pojoAdapterMap.getAdapter(adapterPojo);
+ final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupPojoAdapter(adapterPojo);
if(adapterPojo == null) {
// nothing to check
@@ -1219,7 +1205,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void ensureOidAdapterMapConsistent(final ObjectAdapter adapter) {
final Oid adapterOid = adapter.getOid();
- final ObjectAdapter adapterAccordingToMap = oidAdapterMap.getAdapter(adapterOid);
+ final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupOidAdapter(adapterOid);
if(adapterOid == null) {
// nothing to check
@@ -1554,119 +1540,6 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
/**
- * {@inheritDoc}
- *
- * <p>
- * Note that there is no management of {@link Version}s here. That is
- * because the {@link PersistenceSession4} is expected to manage this.
- *
- * @param hintRootOid - allow a different persistent root oid to be provided.
- */
- private void remapAsPersistent(final ObjectAdapter adapter, RootOid hintRootOid) {
-
- final ObjectAdapter rootAdapter = adapter.getAggregateRoot(); // TODO: REVIEW: think this is redundant; would seem this method is only ever called for roots anyway.
- final RootOid transientRootOid = (RootOid) rootAdapter.getOid();
-
- // no longer true, because isTransient now looks directly at the underlying pojo's state (for entities)
- // and doesn't apply for services.
- // Ensure.ensureThatArg(rootAdapter.isTransient(), is(true), "root adapter should be transient; oid:" + transientRootOid);
- // Ensure.ensureThatArg(transientRootOid.isTransient(), is(true), "root adapter's OID should be transient; oid:" + transientRootOid);
-
- final RootAndCollectionAdapters rootAndCollectionAdapters = new RootAndCollectionAdapters(adapter, this);
-
- LOG.debug("remapAsPersistent: {}", transientRootOid);
- LOG.debug("removing root adapter from oid map");
-
- boolean removed = oidAdapterMap.remove(transientRootOid);
- if (!removed) {
- LOG.warn("could not remove oid: {}", transientRootOid);
- // should we fail here with a more serious error?
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("removing collection adapter(s) from oid map");
- }
- for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
- final Oid collectionOid = collectionAdapter.getOid();
- removed = oidAdapterMap.remove(collectionOid);
- if (!removed) {
- LOG.warn("could not remove collectionOid: {}", collectionOid);
- // should we fail here with a more serious error?
- }
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("updating the Oid");
- }
-
- // intended for testing (bit nasty)
- final RootOid persistedRootOid;
- if(hintRootOid != null) {
- if(hintRootOid.isTransient()) {
- throw new IsisAssertException("hintRootOid must be persistent");
- }
- final ObjectSpecId hintRootOidObjectSpecId = hintRootOid.getObjectSpecId();
- final ObjectSpecId adapterObjectSpecId = adapter.getSpecification().getSpecId();
- if(!hintRootOidObjectSpecId.equals(adapterObjectSpecId)) {
- throw new IsisAssertException("hintRootOid's objectType must be same as that of adapter " +
- "(was: '" + hintRootOidObjectSpecId + "'; adapter's is " + adapterObjectSpecId + "'");
- }
- // ok
- persistedRootOid = hintRootOid;
- } else {
- // normal flow - delegate to OidGenerator to obtain a persistent root oid
- persistedRootOid = createPersistentOrViewModelOid(adapter.getObject());
- }
-
- // associate root adapter with the new Oid, and remap
- if (LOG.isDebugEnabled()) {
- LOG.debug("replacing Oid for root adapter and re-adding into maps; oid is now: {} (was: {})", persistedRootOid.enString(), transientRootOid.enString());
- }
- adapter.replaceOid(persistedRootOid);
- oidAdapterMap.add(persistedRootOid, adapter);
-
- // associate the collection adapters with new Oids, and re-map
- if (LOG.isDebugEnabled()) {
- LOG.debug("replacing Oids for collection adapter(s) and re-adding into maps");
- }
- for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
- final ParentedCollectionOid previousCollectionOid = (ParentedCollectionOid) collectionAdapter.getOid();
- final ParentedCollectionOid persistedCollectionOid = previousCollectionOid.asPersistent(persistedRootOid);
- oidAdapterMap.add(persistedCollectionOid, collectionAdapter);
- }
-
-
- // some object store implementations may replace collection instances (eg ORM may replace with a cglib-enhanced
- // proxy equivalent. So, ensure that the collection adapters still wrap the correct pojos.
- if (LOG.isDebugEnabled()) {
- LOG.debug("synchronizing collection pojos, remapping in pojo map if required");
- }
- for (final OneToManyAssociation otma : rootAndCollectionAdapters.getCollections()) {
- final ObjectAdapter collectionAdapter = rootAndCollectionAdapters.getCollectionAdapter(otma);
-
- final Object collectionPojoWrappedByAdapter = collectionAdapter.getObject();
- final Object collectionPojoActuallyOnPojo = getCollectionPojo(otma, adapter);
-
- if (collectionPojoActuallyOnPojo != collectionPojoWrappedByAdapter) {
- pojoAdapterMap.remove(collectionAdapter);
- collectionAdapter.replacePojo(collectionPojoActuallyOnPojo);
- pojoAdapterMap.add(collectionPojoActuallyOnPojo, collectionAdapter);
- }
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("made persistent {}; was {}", adapter, transientRootOid);
- }
- }
-
- private static Object getCollectionPojo(final OneToManyAssociation association, final ObjectAdapter ownerAdapter) {
- final PropertyOrCollectionAccessorFacet accessor = association.getFacet(PropertyOrCollectionAccessorFacet.class);
- return accessor.getProperty(ownerAdapter, InteractionInitiatedBy.FRAMEWORK);
- }
-
-
-
- /**
* Either returns an existing {@link ObjectAdapter adapter} (as per
* {@link #getAdapterFor(Object)} or {@link #getAdapterFor(Oid)}), otherwise
* re-creates an adapter with the specified (persistent) {@link Oid}.
@@ -1729,13 +1602,13 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void unmap(final ObjectAdapter adapter) {
ensureMapsConsistent(adapter);
- final Oid oid = adapter.getOid();
- if (oid != null) {
- oidAdapterMap.remove(oid);
- }
- pojoAdapterMap.remove(adapter);
+ objectAdapterContext.removeAdapter(adapter);
}
+ /**
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
+ */
+ @Deprecated
private void remapRecreatedPojo(ObjectAdapter adapter, final Object pojo) {
removeAdapter(adapter);
adapter.replacePojo(pojo);
@@ -1815,7 +1688,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
Assert.assertNotNull(adapter);
final Object pojo = adapter.getObject();
- Assert.assertFalse("POJO Map already contains object", pojo, pojoAdapterMap.containsPojo(pojo));
+ Assert.assertFalse("POJO Map already contains object", pojo, objectAdapterContext.containsPojoAdapter(pojo));
if (LOG.isDebugEnabled()) {
// don't interact with the underlying object because may be a ghost
@@ -1834,14 +1707,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
return adapter;
}
- // add all aggregated collections
- final ObjectSpecification objSpec = adapter.getSpecification();
- if (!adapter.isParentedCollection() || adapter.isParentedCollection() && !objSpec.isImmutable()) {
- pojoAdapterMap.add(pojo, adapter);
- }
-
- // order is important - add to pojo map first, then identity map
- oidAdapterMap.add(adapter.getOid(), adapter);
+ objectAdapterContext.addAdapterHonoringSpecImmutability(pojo, adapter);
// must inject after mapping, otherwise infinite loop
servicesInjector.injectServicesInto(pojo);
@@ -2046,7 +1912,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
// persisting
final RootOid persistentOid = createPersistentOrViewModelOid(pojo);
- remapAsPersistent(adapter, persistentOid);
+ objectAdapterContext.remapAsPersistent(adapter, persistentOid, this);
CallbackFacet.Util.callCallback(adapter, PersistedCallbackFacet.class);
postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
index 1f3c89a..1f78654 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
@@ -59,7 +59,6 @@ import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.ensure.Assert;
-import org.apache.isis.core.commons.ensure.IsisAssertException;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.factory.InstanceUtil;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -69,7 +68,6 @@ import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
import org.apache.isis.core.metamodel.adapter.version.Version;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.facets.actcoll.typeof.ElementSpecificationProviderFromTypeOfFacet;
import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
@@ -91,7 +89,6 @@ import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingCallbackFa
import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacet;
import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
-import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
import org.apache.isis.core.metamodel.services.ServicesInjector;
import org.apache.isis.core.metamodel.services.container.query.QueryCardinality;
import org.apache.isis.core.metamodel.spec.FreeStandingList;
@@ -113,9 +110,8 @@ import org.apache.isis.core.runtime.persistence.objectstore.transaction.Persiste
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllInstances;
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
import org.apache.isis.core.runtime.services.RequestScopedService;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.OidAdapterHashMap;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.PojoAdapterHashMap;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.RootAndCollectionAdapters;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy.ObjectAdapterContext;
import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
@@ -136,6 +132,7 @@ public class PersistenceSession5 extends PersistenceSessionBase
implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession5.class);
+ private ObjectAdapterContext objectAdapterContext;
/**
* Initialize the object store so that calls to this object store access
@@ -163,9 +160,8 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
if (LOG.isDebugEnabled()) {
LOG.debug("opening {}", this);
}
-
- oidAdapterMap.open();
- pojoAdapterMap.open();
+
+ objectAdapterContext = ObjectAdapterLegacy.openContext(servicesInjector);
persistenceManager = jdoPersistenceManagerFactory.getPersistenceManager();
@@ -233,7 +229,10 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
/**
* Creates {@link ObjectAdapter adapters} for the service list, ensuring that these are mapped correctly,
* and have the same OIDs as in any previous sessions.
+ *
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
*/
+ @Deprecated
private void initServices() {
final List<Object> registeredServices = servicesInjector.getRegisteredServices();
for (final Object service : registeredServices) {
@@ -244,7 +243,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void remapAsPersistentIfRequired(final ObjectAdapter serviceAdapter) {
if (serviceAdapter.getOid().isTransient()) {
- remapAsPersistent(serviceAdapter, null);
+ objectAdapterContext.remapAsPersistent(serviceAdapter, null, this);
}
}
@@ -255,8 +254,6 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
return command;
}
-
-
// -- close
/**
@@ -310,19 +307,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
"close: failed to close JDO persistenceManager; continuing to avoid memory leakage");
}
- try {
- oidAdapterMap.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
- }
-
- try {
- pojoAdapterMap.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: pojoAdapterMap#close() failed; continuing to avoid memory leakage");
- }
+ objectAdapterContext.close();
this.state = State.CLOSED;
}
@@ -1122,15 +1107,12 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
}
// -- AdapterManager implementation
-
- private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
- private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
-
+
@Override
public ObjectAdapter getAdapterFor(final Object pojo) {
Objects.requireNonNull(pojo);
- return pojoAdapterMap.getAdapter(pojo);
+ return objectAdapterContext.lookupPojoAdapter(pojo);
}
@Override
@@ -1138,7 +1120,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
Objects.requireNonNull(oid);
ensureMapsConsistent(oid);
- return oidAdapterMap.getAdapter(oid);
+ return objectAdapterContext.lookupOidAdapter(oid);
}
@@ -1194,11 +1176,13 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
/**
* Fail early if any problems.
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
*/
+ @Deprecated
private void ensureMapsConsistent(final Oid oid) {
Objects.requireNonNull(oid);
- final ObjectAdapter adapter = oidAdapterMap.getAdapter(oid);
+ final ObjectAdapter adapter = objectAdapterContext.lookupOidAdapter(oid);
if (adapter == null) {
return;
}
@@ -1208,7 +1192,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void ensurePojoAdapterMapConsistent(final ObjectAdapter adapter) {
final Object adapterPojo = adapter.getObject();
- final ObjectAdapter adapterAccordingToMap = pojoAdapterMap.getAdapter(adapterPojo);
+ final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupPojoAdapter(adapterPojo);
if(adapterPojo == null) {
// nothing to check
@@ -1219,7 +1203,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void ensureOidAdapterMapConsistent(final ObjectAdapter adapter) {
final Oid adapterOid = adapter.getOid();
- final ObjectAdapter adapterAccordingToMap = oidAdapterMap.getAdapter(adapterOid);
+ final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupOidAdapter(adapterOid);
if(adapterOid == null) {
// nothing to check
@@ -1554,120 +1538,6 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
return collectionAdapter;
}
-
- /**
- * {@inheritDoc}
- *
- * <p>
- * Note that there is no management of {@link Version}s here. That is
- * because the {@link PersistenceSession5} is expected to manage this.
- *
- * @param hintRootOid - allow a different persistent root oid to be provided.
- */
- private void remapAsPersistent(final ObjectAdapter adapter, RootOid hintRootOid) {
-
- final ObjectAdapter rootAdapter = adapter.getAggregateRoot(); // TODO: REVIEW: think this is redundant; would seem this method is only ever called for roots anyway.
- final RootOid transientRootOid = (RootOid) rootAdapter.getOid();
-
- // no longer true, because isTransient now looks directly at the underlying pojo's state (for entities)
- // and doesn't apply for services.
- // Ensure.ensureThatArg(rootAdapter.isTransient(), is(true), "root adapter should be transient; oid:" + transientRootOid);
- // Ensure.ensureThatArg(transientRootOid.isTransient(), is(true), "root adapter's OID should be transient; oid:" + transientRootOid);
-
- final RootAndCollectionAdapters rootAndCollectionAdapters = new RootAndCollectionAdapters(adapter, this);
-
- LOG.debug("remapAsPersistent: {}", transientRootOid);
- LOG.debug("removing root adapter from oid map");
-
- boolean removed = oidAdapterMap.remove(transientRootOid);
- if (!removed) {
- LOG.warn("could not remove oid: {}", transientRootOid);
- // should we fail here with a more serious error?
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("removing collection adapter(s) from oid map");
- }
- for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
- final Oid collectionOid = collectionAdapter.getOid();
- removed = oidAdapterMap.remove(collectionOid);
- if (!removed) {
- LOG.warn("could not remove collectionOid: {}", collectionOid);
- // should we fail here with a more serious error?
- }
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("updating the Oid");
- }
-
- // intended for testing (bit nasty)
- final RootOid persistedRootOid;
- if(hintRootOid != null) {
- if(hintRootOid.isTransient()) {
- throw new IsisAssertException("hintRootOid must be persistent");
- }
- final ObjectSpecId hintRootOidObjectSpecId = hintRootOid.getObjectSpecId();
- final ObjectSpecId adapterObjectSpecId = adapter.getSpecification().getSpecId();
- if(!hintRootOidObjectSpecId.equals(adapterObjectSpecId)) {
- throw new IsisAssertException("hintRootOid's objectType must be same as that of adapter " +
- "(was: '" + hintRootOidObjectSpecId + "'; adapter's is " + adapterObjectSpecId + "'");
- }
- // ok
- persistedRootOid = hintRootOid;
- } else {
- // normal flow - delegate to OidGenerator to obtain a persistent root oid
- persistedRootOid = createPersistentOrViewModelOid(adapter.getObject());
- }
-
- // associate root adapter with the new Oid, and remap
- if (LOG.isDebugEnabled()) {
- LOG.debug("replacing Oid for root adapter and re-adding into maps; oid is now: {} (was: {})", persistedRootOid.enString(), transientRootOid.enString());
- }
- adapter.replaceOid(persistedRootOid);
- oidAdapterMap.add(persistedRootOid, adapter);
-
- // associate the collection adapters with new Oids, and re-map
- if (LOG.isDebugEnabled()) {
- LOG.debug("replacing Oids for collection adapter(s) and re-adding into maps");
- }
- for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
- final ParentedCollectionOid previousCollectionOid = (ParentedCollectionOid) collectionAdapter.getOid();
- final ParentedCollectionOid persistedCollectionOid = previousCollectionOid.asPersistent(persistedRootOid);
- oidAdapterMap.add(persistedCollectionOid, collectionAdapter);
- }
-
-
- // some object store implementations may replace collection instances (eg ORM may replace with a cglib-enhanced
- // proxy equivalent. So, ensure that the collection adapters still wrap the correct pojos.
- if (LOG.isDebugEnabled()) {
- LOG.debug("synchronizing collection pojos, remapping in pojo map if required");
- }
- for (final OneToManyAssociation otma : rootAndCollectionAdapters.getCollections()) {
- final ObjectAdapter collectionAdapter = rootAndCollectionAdapters.getCollectionAdapter(otma);
-
- final Object collectionPojoWrappedByAdapter = collectionAdapter.getObject();
- final Object collectionPojoActuallyOnPojo = getCollectionPojo(otma, adapter);
-
- if (collectionPojoActuallyOnPojo != collectionPojoWrappedByAdapter) {
- pojoAdapterMap.remove(collectionAdapter);
- collectionAdapter.replacePojo(collectionPojoActuallyOnPojo);
- pojoAdapterMap.add(collectionPojoActuallyOnPojo, collectionAdapter);
- }
- }
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("made persistent {}; was {}", adapter, transientRootOid);
- }
- }
-
- private static Object getCollectionPojo(final OneToManyAssociation association, final ObjectAdapter ownerAdapter) {
- final PropertyOrCollectionAccessorFacet accessor = association.getFacet(PropertyOrCollectionAccessorFacet.class);
- return accessor.getProperty(ownerAdapter, InteractionInitiatedBy.FRAMEWORK);
- }
-
-
-
/**
* Either returns an existing {@link ObjectAdapter adapter} (as per
* {@link #getAdapterFor(Object)} or {@link #getAdapterFor(Oid)}), otherwise
@@ -1731,13 +1601,13 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
private void unmap(final ObjectAdapter adapter) {
ensureMapsConsistent(adapter);
- final Oid oid = adapter.getOid();
- if (oid != null) {
- oidAdapterMap.remove(oid);
- }
- pojoAdapterMap.remove(adapter);
+ objectAdapterContext.removeAdapter(adapter);
}
+ /**
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
+ */
+ @Deprecated
private void remapRecreatedPojo(ObjectAdapter adapter, final Object pojo) {
removeAdapter(adapter);
adapter.replacePojo(pojo);
@@ -1817,7 +1687,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
Assert.assertNotNull(adapter);
final Object pojo = adapter.getObject();
- Assert.assertFalse("POJO Map already contains object", pojo, pojoAdapterMap.containsPojo(pojo));
+ Assert.assertFalse("POJO Map already contains object", pojo, objectAdapterContext.containsPojoAdapter(pojo));
if (LOG.isDebugEnabled()) {
// don't interact with the underlying object because may be a ghost
@@ -1836,14 +1706,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
return adapter;
}
- // add all aggregated collections
- final ObjectSpecification objSpec = adapter.getSpecification();
- if (!adapter.isParentedCollection() || adapter.isParentedCollection() && !objSpec.isImmutable()) {
- pojoAdapterMap.add(pojo, adapter);
- }
-
- // order is important - add to pojo map first, then identity map
- oidAdapterMap.add(adapter.getOid(), adapter);
+ objectAdapterContext.addAdapterHonoringSpecImmutability(pojo, adapter);
// must inject after mapping, otherwise infinite loop
servicesInjector.injectServicesInto(pojo);
@@ -1851,10 +1714,6 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
return adapter;
}
-
-
-
-
// -- TransactionManager delegate methods
protected IsisTransaction getCurrentTransaction() {
return transactionManager.getCurrentTransaction();
@@ -2048,7 +1907,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement {
// persisting
final RootOid persistentOid = createPersistentOrViewModelOid(pojo);
- remapAsPersistent(adapter, persistentOid);
+ objectAdapterContext.remapAsPersistent(adapter, persistentOid, this);
CallbackFacet.Util.callCallback(adapter, PersistedCallbackFacet.class);
postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java
new file mode 100644
index 0000000..d89524f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java
@@ -0,0 +1,234 @@
+/*
+ * 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.isis.core.runtime.system.persistence.adaptermanager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.core.commons.ensure.IsisAssertException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+public class ObjectAdapterLegacy {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterLegacy.class);
+
+ public static ObjectAdapterContext openContext(ServicesInjector servicesInjector) {
+ final ObjectAdapterContext objectAdapterContext = new ObjectAdapterContext(servicesInjector);
+ objectAdapterContext.open();
+ return objectAdapterContext;
+ }
+
+ public static class ObjectAdapterContext /*implements AdapterManager*/ {
+ private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
+ private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
+ private final ServicesInjector servicesInjector;
+
+ private ObjectAdapterContext(ServicesInjector servicesInjector) {
+ this.servicesInjector = servicesInjector;
+ }
+
+ // -- LIFE-CYCLING
+
+ public void open() {
+ oidAdapterMap.open();
+ pojoAdapterMap.open();
+ }
+
+ public void close() {
+
+ try {
+ oidAdapterMap.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
+ }
+
+ try {
+ pojoAdapterMap.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("close: pojoAdapterMap#close() failed; continuing to avoid memory leakage");
+ }
+ }
+
+ public boolean containsPojoAdapter(Object pojo) {
+ return pojoAdapterMap.containsPojo(pojo);
+ }
+
+ public ObjectAdapter lookupPojoAdapter(Object pojo) {
+ return pojoAdapterMap.getAdapter(pojo);
+ }
+
+ public ObjectAdapter lookupOidAdapter(Oid oid) {
+ return oidAdapterMap.getAdapter(oid);
+ }
+
+ public void removeAdapter(ObjectAdapter adapter) {
+ final Oid oid = adapter.getOid();
+ if (oid != null) {
+ oidAdapterMap.remove(oid);
+ }
+ pojoAdapterMap.remove(adapter);
+ }
+
+ // ------------------------------------------------------------------------------------------------
+
+ public void addAdapterHonoringSpecImmutability(Object pojo, ObjectAdapter adapter) {
+ // add all aggregated collections
+ final ObjectSpecification objSpec = adapter.getSpecification();
+ if (!adapter.isParentedCollection() || adapter.isParentedCollection() && !objSpec.isImmutable()) {
+ pojoAdapterMap.add(pojo, adapter);
+ }
+
+ // order is important - add to pojo map first, then identity map
+ oidAdapterMap.add(adapter.getOid(), adapter);
+ }
+
+ /**
+ * was in PersisenceSessionX, temporarily moved here to successfully compile
+ *
+ * <p>
+ * Note that there is no management of {@link Version}s here. That is
+ * because the {@link PersistenceSession5} is expected to manage this.
+ *
+ * @param hintRootOid - allow a different persistent root oid to be provided.
+ * @param session
+ */
+ public void remapAsPersistent(final ObjectAdapter adapter, RootOid hintRootOid, PersistenceSession session) {
+
+ final ObjectAdapter rootAdapter = adapter.getAggregateRoot(); // TODO: REVIEW: think this is redundant; would seem this method is only ever called for roots anyway.
+ final RootOid transientRootOid = (RootOid) rootAdapter.getOid();
+
+ // no longer true, because isTransient now looks directly at the underlying pojo's state (for entities)
+ // and doesn't apply for services.
+ // Ensure.ensureThatArg(rootAdapter.isTransient(), is(true), "root adapter should be transient; oid:" + transientRootOid);
+ // Ensure.ensureThatArg(transientRootOid.isTransient(), is(true), "root adapter's OID should be transient; oid:" + transientRootOid);
+
+ final RootAndCollectionAdapters rootAndCollectionAdapters = new RootAndCollectionAdapters(adapter, session);
+
+ LOG.debug("remapAsPersistent: {}", transientRootOid);
+ LOG.debug("removing root adapter from oid map");
+
+ boolean removed = oidAdapterMap.remove(transientRootOid);
+ if (!removed) {
+ LOG.warn("could not remove oid: {}", transientRootOid);
+ // should we fail here with a more serious error?
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("removing collection adapter(s) from oid map");
+ }
+ for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
+ final Oid collectionOid = collectionAdapter.getOid();
+ removed = oidAdapterMap.remove(collectionOid);
+ if (!removed) {
+ LOG.warn("could not remove collectionOid: {}", collectionOid);
+ // should we fail here with a more serious error?
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("updating the Oid");
+ }
+
+ // intended for testing (bit nasty)
+ final RootOid persistedRootOid;
+ if(hintRootOid != null) {
+ if(hintRootOid.isTransient()) {
+ throw new IsisAssertException("hintRootOid must be persistent");
+ }
+ final ObjectSpecId hintRootOidObjectSpecId = hintRootOid.getObjectSpecId();
+ final ObjectSpecId adapterObjectSpecId = adapter.getSpecification().getSpecId();
+ if(!hintRootOidObjectSpecId.equals(adapterObjectSpecId)) {
+ throw new IsisAssertException("hintRootOid's objectType must be same as that of adapter " +
+ "(was: '" + hintRootOidObjectSpecId + "'; adapter's is " + adapterObjectSpecId + "'");
+ }
+ // ok
+ persistedRootOid = hintRootOid;
+ } else {
+ // normal flow - delegate to OidGenerator to obtain a persistent root oid
+ persistedRootOid = session.createPersistentOrViewModelOid(adapter.getObject());
+ }
+
+ // associate root adapter with the new Oid, and remap
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("replacing Oid for root adapter and re-adding into maps; oid is now: {} (was: {})", persistedRootOid.enString(), transientRootOid.enString());
+ }
+ adapter.replaceOid(persistedRootOid);
+ oidAdapterMap.add(persistedRootOid, adapter);
+
+ // associate the collection adapters with new Oids, and re-map
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("replacing Oids for collection adapter(s) and re-adding into maps");
+ }
+ for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
+ final ParentedCollectionOid previousCollectionOid = (ParentedCollectionOid) collectionAdapter.getOid();
+ final ParentedCollectionOid persistedCollectionOid = previousCollectionOid.asPersistent(persistedRootOid);
+ oidAdapterMap.add(persistedCollectionOid, collectionAdapter);
+ }
+
+
+ // some object store implementations may replace collection instances (eg ORM may replace with a cglib-enhanced
+ // proxy equivalent. So, ensure that the collection adapters still wrap the correct pojos.
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("synchronizing collection pojos, remapping in pojo map if required");
+ }
+ for (final OneToManyAssociation otma : rootAndCollectionAdapters.getCollections()) {
+ final ObjectAdapter collectionAdapter = rootAndCollectionAdapters.getCollectionAdapter(otma);
+
+ final Object collectionPojoWrappedByAdapter = collectionAdapter.getObject();
+ final Object collectionPojoActuallyOnPojo = getCollectionPojo(otma, adapter);
+
+ if (collectionPojoActuallyOnPojo != collectionPojoWrappedByAdapter) {
+ pojoAdapterMap.remove(collectionAdapter);
+ collectionAdapter.replacePojo(collectionPojoActuallyOnPojo);
+ pojoAdapterMap.add(collectionPojoActuallyOnPojo, collectionAdapter);
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("made persistent {}; was {}", adapter, transientRootOid);
+ }
+ }
+
+ private static Object getCollectionPojo(final OneToManyAssociation association, final ObjectAdapter ownerAdapter) {
+ final PropertyOrCollectionAccessorFacet accessor = association.getFacet(PropertyOrCollectionAccessorFacet.class);
+ return accessor.getProperty(ownerAdapter, InteractionInitiatedBy.FRAMEWORK);
+ }
+
+
+
+
+
+ }
+
+
+
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/OidAdapterHashMap.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/OidAdapterHashMap.java
index f94633d..da321e1 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/OidAdapterHashMap.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/OidAdapterHashMap.java
@@ -33,8 +33,10 @@ import org.apache.isis.core.metamodel.adapter.oid.Oid;
/**
* A map of the objects' identities and the adapters' of the objects.
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
*/
-public class OidAdapterHashMap implements Iterable<Oid>, SessionScopedComponent {
+@Deprecated
+class OidAdapterHashMap implements Iterable<Oid>, SessionScopedComponent {
private static final Logger LOG = LoggerFactory.getLogger(OidAdapterHashMap.class);
public static final int DEFAULT_OID_ADAPTER_MAP_SIZE = 100;
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/PojoAdapterHashMap.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/PojoAdapterHashMap.java
index 2710f3a..e256a49 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/PojoAdapterHashMap.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/PojoAdapterHashMap.java
@@ -30,7 +30,11 @@ import org.slf4j.LoggerFactory;
import org.apache.isis.core.commons.components.SessionScopedComponent;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-public class PojoAdapterHashMap implements Iterable<ObjectAdapter>, SessionScopedComponent {
+/**
+ * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
+ */
+@Deprecated
+class PojoAdapterHashMap implements Iterable<ObjectAdapter>, SessionScopedComponent {
private static class IdentityHashKey {
private final Object pojo;