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 30842ab1d93ff5a0930d1e9d2c809798419a2320 Author: Andi Huber <ahu...@apache.org> AuthorDate: Mon Sep 10 16:15:13 2018 +0200 ISIS-1976: further remove OA references from PS API Task-Url: https://issues.apache.org/jira/browse/ISIS-1976 --- .../metamodel/adapter/ObjectAdapterProvider.java | 32 +++++ .../system/persistence/PersistenceSession4.java | 155 +++------------------ .../system/persistence/PersistenceSession5.java | 153 +++----------------- .../PersistenceSessionServiceInternalDefault.java | 27 +++- .../system/persistence/PersistenceSession.java | 20 +-- .../adaptermanager/ObjectAdapterContext.java | 81 +---------- ...ctAdapterContext_ObjectAdapterByIdProvider.java | 3 +- ...ObjectAdapterContext_ObjectAdapterProvider.java | 14 ++ .../resources/DomainObjectResourceServerside.java | 2 +- .../restfulobjects/server/util/OidUtils.java | 53 ++++++- .../DelegatingInvocationHandlerDefault.java | 5 +- 11 files changed, 174 insertions(+), 371 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java index 773f292..34ce26a 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java @@ -45,6 +45,7 @@ public interface ObjectAdapterProvider { * @param pojo * @return oid for the given domain object */ + @Programmatic default @Nullable Oid oidFor(@Nullable Object domainObject) { return mapIfPresentElse(adapterFor(domainObject), ObjectAdapter::getOid, null); } @@ -82,6 +83,27 @@ public interface ObjectAdapterProvider { final Function<ObjectSpecId, RootOid> rootOidFactory); + // -- DOMAIN OBJECT CREATION SUPPORT + + /** + * <p> + * Creates a new instance of the specified type and returns it. + * + * <p> + * The returned object will be initialised (had the relevant callback + * lifecycle methods invoked). + * + * <p> + * While creating the object it will be initialised with default values and + * its created lifecycle method (its logical constructor) will be invoked. + * + */ + ObjectAdapter newTransientInstance(ObjectSpecification objectSpec); + + @Nullable ObjectAdapter recreateViewModelInstance(ObjectSpecification objectSpec, @Nullable final String memento); + + // -- SERVICE LOOKUP + List<ObjectAdapter> getServices(); @@ -123,6 +145,16 @@ public interface ObjectAdapterProvider { } @Programmatic + default ObjectAdapter newTransientInstance(ObjectSpecification objectSpec) { + return getObjectAdapterProvider().newTransientInstance(objectSpec); + } + + @Programmatic + default ObjectAdapter recreateViewModelInstance(ObjectSpecification objectSpec, final String memento) { + return getObjectAdapterProvider().recreateViewModelInstance(objectSpec, memento); + } + + @Programmatic default List<ObjectAdapter> getServices() { return getObjectAdapterProvider().getServices(); } 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 26ff4c0..6869eab 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 @@ -48,13 +48,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.isis.applib.query.Query; -import org.apache.isis.applib.services.bookmark.Bookmark; -import org.apache.isis.applib.services.bookmark.BookmarkService; import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer; import org.apache.isis.applib.services.iactn.Interaction; import org.apache.isis.core.commons.authentication.AuthenticationSession; -import org.apache.isis.core.commons.ensure.Assert; import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider; @@ -65,7 +62,7 @@ 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.facets.collections.modify.CollectionFacetUtils; +import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedCallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacet; @@ -79,16 +76,13 @@ import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedCallbackFac import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedLifecycleEventFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingCallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacet; -import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet; 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; -import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.runtime.persistence.FixturesInstalledFlag; import org.apache.isis.core.runtime.persistence.NotPersistableException; import org.apache.isis.core.runtime.persistence.ObjectNotFoundException; -import org.apache.isis.core.runtime.persistence.PojoRecreationException; import org.apache.isis.core.runtime.persistence.PojoRefreshException; import org.apache.isis.core.runtime.persistence.UnsupportedFindException; import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand; @@ -324,7 +318,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { } } - commandService.complete(command); command.flushActionDomainEvents(); @@ -336,12 +329,12 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { @Override public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) { final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.MULTIPLE); - return CollectionFacetUtils.convertToAdapterList(instances); + return CollectionFacet.Utils.convertToAdapterList(instances); } @Override public <T> ObjectAdapter firstMatchingQuery(final Query<T> query) { final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.SINGLE); - final List<ObjectAdapter> list = CollectionFacetUtils.convertToAdapterList(instances); + final List<ObjectAdapter> list = CollectionFacet.Utils.convertToAdapterList(instances); return list.size() > 0 ? list.get(0) : null; } @@ -409,36 +402,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return persistenceQueryProcessor.process((Q) persistenceQuery); } - // -- createTransientInstance, createViewModelInstance - - /** - * Create a root or standalone {@link ObjectAdapter adapter}. - * - * <p> - * Creates a new instance of the specified type and returns it in an adapter. - * - * <p> - * The returned object will be initialised (had the relevant callback - * lifecycle methods invoked). - * - * <p> - * While creating the object it will be initialised with default values and - * its created lifecycle method (its logical constructor) will be invoked. - * - * <p> - * This method is ultimately delegated to by the - * {@link org.apache.isis.applib.DomainObjectContainer}. - */ - @Override - public ObjectAdapter createTransientInstance(final ObjectSpecification objectSpec) { - return objectAdapterContext.newInstance(objectSpec); - } - - @Override - public ObjectAdapter createViewModelInstance(final ObjectSpecification objectSpec, final String memento) { - return objectAdapterContext.recreateInstance(objectSpec, memento); - } - // -- fixture installation @@ -526,6 +489,19 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { } return result; } + + @Override + public Object fetchPersistentPojoInTransaction(final RootOid oid) { + + Objects.requireNonNull(oid); + + return transactionManager.executeWithinTransaction(()-> { + LOG.debug("getObject; oid={}", oid); + + final Object pojo = fetchPersistentPojo(oid); + return objectAdapterContext.addRecreatedPojoToCache(oid, pojo).getObject(); + }); + } @Override public Map<RootOid,Object> fetchPersistentPojos(final List<RootOid> rootOids) { @@ -627,6 +603,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { refreshRoot(domainObject); }); } + // -- makePersistent @@ -659,7 +636,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { getTransactionManager().executeWithinTransaction(()->{ makePersistentTransactionAssumed(adapter); // clear out the map of transient -> persistent - // already empty // PersistenceSession5.this.persistentByTransient.clear(); + // already empty // PersistenceSession4.this.persistentByTransient.clear(); }); } @@ -790,48 +767,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return rootadapter; } - // -- AdapterManager implementation - - @Override - public ObjectAdapter adapterForAny(RootOid rootOid) { - - final ObjectSpecId specId = rootOid.getObjectSpecId(); - final ObjectSpecification spec = getSpecificationLoader().lookupBySpecId(specId); - if(spec == null) { - // eg "NONEXISTENT:123" - return null; - } - - if(spec.containsFacet(ViewModelFacet.class)) { - - // this is a hack; the RO viewer when rendering the URL for the view model loses the "view model" indicator - // ("*") from the specId, meaning that the marshalling logic above in RootOidDefault.deString() creates an - // oid in the wrong state. The code below checks for this and recreates the oid with the current state of 'view model' - if(!rootOid.isViewModel()) { - rootOid = new RootOid(rootOid.getObjectSpecId(), rootOid.getIdentifier(), Oid.State.VIEWMODEL); - } - - try { - return adapterFor(rootOid); - } catch(final ObjectNotFoundException ex) { - return null; - } catch(final PojoRecreationException ex) { - return null; - } - } else { - try { - ObjectAdapter objectAdapter = loadObjectInTransaction(rootOid); - return objectAdapter.isTransient() ? null : objectAdapter; - } catch(final ObjectNotFoundException ex) { - return null; - } - } - } - - // -- TransactionManager delegate methods - protected IsisTransaction getCurrentTransaction() { - return transactionManager.getCurrentTransaction(); - } // -- FrameworkSynchronizer delegate methods @@ -883,7 +818,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { final String currentUser = authenticationSession.getUserName(); final ConcurrencyException abortCause = new ConcurrencyException(currentUser, thisOid, thisVersion, otherVersion); - getCurrentTransaction().setAbortCause(abortCause); + + transactionManager.getCurrentTransaction().setAbortCause(abortCause); } else { LOG.info("concurrency conflict detected but suppressed, on {} ({})", thisOid, otherVersion); @@ -1058,57 +994,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return Utils.getVersionIfAny(pojo, authenticationSession); } - // -- DomainObjectServices impl - - @Override - public Object lookup( - final Bookmark bookmark, - final BookmarkService.FieldResetPolicy fieldResetPolicy) { - final RootOid oid = RootOid.create(bookmark); - - final ObjectAdapter adapter = adapterFor(oid); - if(adapter == null) { - return null; - } - - //FIXME[ISIS-1976] - Assert.assertEquals("expected same", oid.isViewModel(), adapter.getSpecification().isViewModel()); - - final boolean denyRefresh = - fieldResetPolicy == BookmarkService.FieldResetPolicy.DONT_REFRESH || - oid.isViewModel(); - - if(denyRefresh) { - loadObjectInTransaction(oid); - } else { - refreshRootInTransaction(adapter.getObject()); - } - return adapter.getObject(); - } + // -- - //FIXME[ISIS-1976] already moved - @Deprecated - private ObjectAdapter loadObjectInTransaction(final RootOid oid) { - - // can be either a view model or a persistent entity. - - Objects.requireNonNull(oid); - - final ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(oid); - if (adapter != null) { - return adapter; - } - - return transactionManager.executeWithinTransaction( - ()-> { - LOG.debug("getObject; oid={}", oid); - - final Object pojo = fetchPersistentPojo(oid); - return objectAdapterContext.addRecreatedPojoToCache(oid, pojo); - }); - } - - @Override public boolean isTransient(@Nullable Object pojo) { if (pojo!=null && pojo instanceof Persistable) { 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 38e7d19..d0f879c 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 @@ -48,13 +48,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.isis.applib.query.Query; -import org.apache.isis.applib.services.bookmark.Bookmark; -import org.apache.isis.applib.services.bookmark.BookmarkService; import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer; import org.apache.isis.applib.services.iactn.Interaction; +import org.apache.isis.commons.internal.exceptions._Exceptions; import org.apache.isis.core.commons.authentication.AuthenticationSession; -import org.apache.isis.core.commons.ensure.Assert; import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider; @@ -65,7 +63,7 @@ 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.facets.collections.modify.CollectionFacetUtils; +import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedCallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacet; @@ -79,16 +77,13 @@ import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedCallbackFac import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedLifecycleEventFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingCallbackFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacet; -import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet; 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; -import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.runtime.persistence.FixturesInstalledFlag; import org.apache.isis.core.runtime.persistence.NotPersistableException; import org.apache.isis.core.runtime.persistence.ObjectNotFoundException; -import org.apache.isis.core.runtime.persistence.PojoRecreationException; import org.apache.isis.core.runtime.persistence.PojoRefreshException; import org.apache.isis.core.runtime.persistence.UnsupportedFindException; import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand; @@ -324,7 +319,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { } } - commandService.complete(command); command.flushActionDomainEvents(); @@ -336,12 +330,12 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { @Override public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) { final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.MULTIPLE); - return CollectionFacetUtils.convertToAdapterList(instances); + return CollectionFacet.Utils.convertToAdapterList(instances); } @Override public <T> ObjectAdapter firstMatchingQuery(final Query<T> query) { final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.SINGLE); - final List<ObjectAdapter> list = CollectionFacetUtils.convertToAdapterList(instances); + final List<ObjectAdapter> list = CollectionFacet.Utils.convertToAdapterList(instances); return list.size() > 0 ? list.get(0) : null; } @@ -409,36 +403,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return persistenceQueryProcessor.process((Q) persistenceQuery); } - // -- createTransientInstance, createViewModelInstance - - /** - * Create a root or standalone {@link ObjectAdapter adapter}. - * - * <p> - * Creates a new instance of the specified type and returns it in an adapter. - * - * <p> - * The returned object will be initialised (had the relevant callback - * lifecycle methods invoked). - * - * <p> - * While creating the object it will be initialised with default values and - * its created lifecycle method (its logical constructor) will be invoked. - * - * <p> - * This method is ultimately delegated to by the - * {@link org.apache.isis.applib.DomainObjectContainer}. - */ - @Override - public ObjectAdapter createTransientInstance(final ObjectSpecification objectSpec) { - return objectAdapterContext.newInstance(objectSpec); - } - - @Override - public ObjectAdapter createViewModelInstance(final ObjectSpecification objectSpec, final String memento) { - return objectAdapterContext.recreateInstance(objectSpec, memento); - } - // -- fixture installation @@ -526,6 +490,19 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { } return result; } + + @Override + public Object fetchPersistentPojoInTransaction(final RootOid oid) { + + Objects.requireNonNull(oid); + + return transactionManager.executeWithinTransaction(()-> { + LOG.debug("getObject; oid={}", oid); + + final Object pojo = fetchPersistentPojo(oid); + return objectAdapterContext.addRecreatedPojoToCache(oid, pojo).getObject(); + }); + } @Override public Map<RootOid,Object> fetchPersistentPojos(final List<RootOid> rootOids) { @@ -791,48 +768,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return rootadapter; } - // -- AdapterManager implementation - - @Override - public ObjectAdapter adapterForAny(RootOid rootOid) { - - final ObjectSpecId specId = rootOid.getObjectSpecId(); - final ObjectSpecification spec = getSpecificationLoader().lookupBySpecId(specId); - if(spec == null) { - // eg "NONEXISTENT:123" - return null; - } - - if(spec.containsFacet(ViewModelFacet.class)) { - - // this is a hack; the RO viewer when rendering the URL for the view model loses the "view model" indicator - // ("*") from the specId, meaning that the marshalling logic above in RootOidDefault.deString() creates an - // oid in the wrong state. The code below checks for this and recreates the oid with the current state of 'view model' - if(!rootOid.isViewModel()) { - rootOid = new RootOid(rootOid.getObjectSpecId(), rootOid.getIdentifier(), Oid.State.VIEWMODEL); - } - - try { - return adapterFor(rootOid); - } catch(final ObjectNotFoundException ex) { - return null; - } catch(final PojoRecreationException ex) { - return null; - } - } else { - try { - ObjectAdapter objectAdapter = loadObjectInTransaction(rootOid); - return objectAdapter.isTransient() ? null : objectAdapter; - } catch(final ObjectNotFoundException ex) { - return null; - } - } - } - - // -- TransactionManager delegate methods - protected IsisTransaction getCurrentTransaction() { - return transactionManager.getCurrentTransaction(); - } // -- FrameworkSynchronizer delegate methods @@ -884,7 +819,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { final String currentUser = authenticationSession.getUserName(); final ConcurrencyException abortCause = new ConcurrencyException(currentUser, thisOid, thisVersion, otherVersion); - getCurrentTransaction().setAbortCause(abortCause); + + transactionManager.getCurrentTransaction().setAbortCause(abortCause); } else { LOG.info("concurrency conflict detected but suppressed, on {} ({})", thisOid, otherVersion); @@ -921,6 +857,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { public String identifierFor(final Object pojo) { final Object jdoOid = getPersistenceManager().getObjectId(pojo); if(jdoOid==null) { + _Exceptions.throwUnexpectedCodeReach(); return UUID.randomUUID().toString(); //FIXME[ISIS-1976] should be guarded against somewhere else } @@ -1059,56 +996,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement { return Utils.getVersionIfAny(pojo, authenticationSession); } - // -- DomainObjectServices impl - - @Override - public Object lookup( - final Bookmark bookmark, - final BookmarkService.FieldResetPolicy fieldResetPolicy) { - final RootOid oid = RootOid.create(bookmark); - - final ObjectAdapter adapter = adapterFor(oid); - if(adapter == null) { - return null; - } - - //FIXME[ISIS-1976] - Assert.assertEquals("expected same", oid.isViewModel(), adapter.getSpecification().isViewModel()); - - final boolean denyRefresh = - fieldResetPolicy == BookmarkService.FieldResetPolicy.DONT_REFRESH || - oid.isViewModel(); - - if(denyRefresh) { - loadObjectInTransaction(oid); - } else { - refreshRootInTransaction(adapter.getObject()); - } - return adapter.getObject(); - } + // -- - //FIXME[ISIS-1976] already moved - @Deprecated - private ObjectAdapter loadObjectInTransaction(final RootOid oid) { - - // can be either a view model or a persistent entity. - - Objects.requireNonNull(oid); - - final ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(oid); - if (adapter != null) { - return adapter; - } - - return transactionManager.executeWithinTransaction( - ()-> { - LOG.debug("getObject; oid={}", oid); - - final Object pojo = fetchPersistentPojo(oid); - return objectAdapterContext.addRecreatedPojoToCache(oid, pojo); - }); - } - @Override public boolean isTransient(@Nullable Object pojo) { if (pojo!=null && pojo instanceof Persistable) { diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java index 4ba74ad..901bb95 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/persistsession/PersistenceSessionServiceInternalDefault.java @@ -35,6 +35,7 @@ import org.apache.isis.applib.services.bookmark.BookmarkService; import org.apache.isis.applib.services.command.Command; import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.xactn.TransactionState; +import org.apache.isis.commons.internal.exceptions._Exceptions; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider; import org.apache.isis.core.metamodel.adapter.oid.Oid; @@ -71,19 +72,39 @@ public class PersistenceSessionServiceInternalDefault implements PersistenceSess @Override public ObjectAdapter createTransientInstance(final ObjectSpecification spec) { - return getPersistenceSession().createTransientInstance(spec); + return getPersistenceSession().newTransientInstance(spec); } @Override public ObjectAdapter createViewModelInstance(ObjectSpecification spec, String memento) { - return getPersistenceSession().createViewModelInstance(spec, memento); + return getPersistenceSession().recreateViewModelInstance(spec, memento); } @Override public Object lookup( final Bookmark bookmark, final BookmarkService.FieldResetPolicy fieldResetPolicy) { - return getPersistenceSession().lookup(bookmark, fieldResetPolicy); + + final RootOid oid = RootOid.create(bookmark); + final PersistenceSession ps = getPersistenceSession(); + final boolean denyRefresh = fieldResetPolicy == BookmarkService.FieldResetPolicy.DONT_REFRESH; + + if(oid.isViewModel()) { + //FIXME[ISIS-1976] if code is reachable requires separate view model handler + throw _Exceptions.unexpectedCodeReach(); + } else if(denyRefresh) { + return ps.fetchPersistentPojoInTransaction(oid); + } else { + + final ObjectAdapter adapter = adapterFor(oid); + if(adapter == null) { + return null; + } + + ps.refreshRootInTransaction(adapter.getObject()); + return adapter.getObject(); + } + } @Override diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java index 3c63285..f26e3c3 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java @@ -22,18 +22,14 @@ import java.util.Map; import javax.jdo.PersistenceManager; import org.apache.isis.applib.query.Query; -import org.apache.isis.applib.services.bookmark.Bookmark; -import org.apache.isis.applib.services.bookmark.BookmarkService.FieldResetPolicy; import org.apache.isis.core.commons.components.SessionScopedComponent; import org.apache.isis.core.commons.config.IsisConfiguration; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider; import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider; -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.services.ServicesInjector; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand; import org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource; import org.apache.isis.core.runtime.runner.opts.OptionHandlerFixtureAbstract; @@ -68,12 +64,14 @@ extends void refreshRoot(Object domainObject); /** - * Re-initialises the fields of an object. If the object is unresolved then + * Re-initializes the fields of an object. If the object is unresolved then * the object's missing data should be retrieved from the persistence * mechanism and be used to set up the value objects and associations. + * @since 2.0.0-M2 */ void refreshRootInTransaction(Object domainObject); + /** * @param pojo a persistable object * @return String representing an object's id. @@ -90,6 +88,8 @@ extends /**@since 2.0.0-M2*/ Object fetchPersistentPojo(RootOid rootOid); /**@since 2.0.0-M2*/ + Object fetchPersistentPojoInTransaction(final RootOid oid); + /**@since 2.0.0-M2*/ Map<RootOid, Object> fetchPersistentPojos(List<RootOid> rootOids); @@ -159,13 +159,8 @@ extends // -- TODO remove ObjectAdapter references from API - ObjectAdapter adapterForAny(RootOid rootOid); <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query); - ObjectAdapter createTransientInstance(ObjectSpecification spec); - - ObjectAdapter createViewModelInstance(ObjectSpecification spec, String memento); - void destroyObjectInTransaction(ObjectAdapter adapter); <T> ObjectAdapter firstMatchingQuery(final Query<T> query); @@ -178,9 +173,4 @@ extends void execute(List<PersistenceCommand> persistenceCommandList); - Object lookup(Bookmark bookmark, FieldResetPolicy fieldResetPolicy); - - - - } diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java index 4de6fb5..1880004 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java @@ -22,8 +22,6 @@ import java.util.Objects; import java.util.UUID; import java.util.function.Function; -import javax.annotation.Nullable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -137,7 +135,7 @@ public class ObjectAdapterContext { private final ObjectAdapterContext_NewIdentifier newIdentifierMixin; private final ObjectAdapterContext_ObjectAdapterByIdProvider objectAdapterByIdProviderMixin; private final ObjectAdapterContext_DependencyInjection dependencyInjectionMixin; - private final ObjectAdapterContext_ObjectCreation objectReCreationMixin; + final ObjectAdapterContext_ObjectCreation objectCreationMixin; private final ObjectAdapterContext_LifecycleEventSupport lifecycleEventMixin; private ObjectAdapterContext( @@ -154,7 +152,7 @@ public class ObjectAdapterContext { this.newIdentifierMixin = new ObjectAdapterContext_NewIdentifier(this, persistenceSession); this.objectAdapterByIdProviderMixin = new ObjectAdapterContext_ObjectAdapterByIdProvider(this, persistenceSession, authenticationSession); this.dependencyInjectionMixin = new ObjectAdapterContext_DependencyInjection(this, persistenceSession); - this.objectReCreationMixin = new ObjectAdapterContext_ObjectCreation(this, persistenceSession); + this.objectCreationMixin = new ObjectAdapterContext_ObjectCreation(this, persistenceSession); this.lifecycleEventMixin = new ObjectAdapterContext_LifecycleEventSupport(this, persistenceSession); this.persistenceSession = persistenceSession; @@ -351,16 +349,6 @@ public class ObjectAdapterContext { return mementoSupportMixin; } - // -- DOMAIN OBJECT CREATION SUPPORT - - public ObjectAdapter newInstance(ObjectSpecification objectSpec) { - return objectReCreationMixin.newInstance(objectSpec); - } - - public ObjectAdapter recreateInstance(ObjectSpecification objectSpec, @Nullable final String memento) { - return objectReCreationMixin.recreateInstance(objectSpec, memento); - } - // -- LIFECYCLE EVENT SUPPORT public void postLifecycleEventIfRequired( @@ -506,71 +494,6 @@ public class ObjectAdapterContext { return newAdapter; } - /** - * Loads the object identified by the specified {@link RootOid}. - * - * <p> - * That is, it retrieves the object identified by the specified {@link RootOid} from the object - * store. - * - * <p>The cache should be checked first and, if the object is cached, - * the cached version should be returned. It is important that if this - * method is called again, while the originally returned object is in - * working memory, then this method must return that same Java object. - * - * <p> - * Assuming that the object is not cached then the data for the object - * should be retrieved from the persistence mechanism and the object - * recreated (as describe previously). The specified OID should then be - * assigned to the recreated object by calling its <method>setOID </method>. - * Before returning the object its resolved flag should also be set by - * calling its <method>setResolved </method> method as well. - * - * <p> - * If the persistence mechanism does not known of an object with the - * specified {@link RootOid} then a {@link org.apache.isis.core.runtime.persistence.ObjectNotFoundException} should be - * thrown. - * - * <p> - * Note that the OID could be for an internal collection, and is - * therefore related to the parent object (using a {@link ParentedCollectionOid}). - * The elements for an internal collection are commonly stored as - * part of the parent object, so to get element the parent object needs to - * be retrieved first, and the internal collection can be got from that. - * - * <p> - * Returns the stored {@link ObjectAdapter} object. - * - * - * @return the requested {@link ObjectAdapter} that has the specified - * {@link RootOid}. - * - * @throws org.apache.isis.core.runtime.persistence.ObjectNotFoundException - * when no object corresponding to the oid can be found - */ - private ObjectAdapter loadObjectInTransaction(final RootOid oid) { - - // can be either a view model or a persistent entity. - - Objects.requireNonNull(oid); - - final ObjectAdapter adapter = lookupAdapterFor(oid); - if (adapter != null) { - return adapter; - } - - return persistenceSession.getTransactionManager().executeWithinTransaction( - ()-> { - LOG.debug("getObject; oid={}", oid); - - final Object pojo = persistenceSession.fetchPersistentPojo(oid); - return addRecreatedPojoToCache(oid, pojo); - }); - } - - - - } \ No newline at end of file diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java index 3253e52..1de4fe4 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.apache.isis.commons.internal.collections._Lists; import org.apache.isis.commons.internal.collections._Maps; +import org.apache.isis.commons.internal.exceptions._Exceptions; import org.apache.isis.core.commons.authentication.AuthenticationSession; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider; @@ -127,7 +128,7 @@ class ObjectAdapterContext_ObjectAdapterByIdProvider implements ObjectAdapterByI //FIXME[ISIS-1976] remove guard final ObjectAdapter serviceAdapter = objectAdapterContext.lookupServiceAdapterFor(rootOid); if (serviceAdapter != null) { - //_Exceptions.unexpectedCodeReach(); + _Exceptions.unexpectedCodeReach(); return serviceAdapter; } diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java index ab92f47..969523a 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java @@ -137,6 +137,20 @@ class ObjectAdapterContext_ObjectAdapterProvider implements ObjectAdapterProvide return adapter; } + // -- DOMAIN OBJECT CREATION SUPPORT + + @Override + public ObjectAdapter newTransientInstance(ObjectSpecification objectSpec) { + return objectAdapterContext.objectCreationMixin.newInstance(objectSpec); + } + + @Override + public ObjectAdapter recreateViewModelInstance(ObjectSpecification objectSpec, final String memento) { + return objectAdapterContext.objectCreationMixin.recreateInstance(objectSpec, memento); + } + + // -- SERVICE SUPPORT + @Override public List<ObjectAdapter> getServices() { return serviceAdapters.get(); diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainObjectResourceServerside.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainObjectResourceServerside.java index 6b7dd1b..2c36cd5 100644 --- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainObjectResourceServerside.java +++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainObjectResourceServerside.java @@ -99,7 +99,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements throw RestfulObjectsApplicationException.createWithMessage(HttpStatusCode.BAD_REQUEST, "Could not determine type of domain object to persist (no class with domainType Id of '%s')", domainType); } - final ObjectAdapter objectAdapter = getResourceContext().getPersistenceSession().createTransientInstance(domainTypeSpec); + final ObjectAdapter objectAdapter = getResourceContext().getPersistenceSession().newTransientInstance(domainTypeSpec); final ObjectAdapterUpdateHelper updateHelper = new ObjectAdapterUpdateHelper(getResourceContext(), objectAdapter); diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java index f79e320..7058cd3 100644 --- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java +++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/OidUtils.java @@ -19,8 +19,14 @@ package org.apache.isis.viewer.restfulobjects.server.util; 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.OidMarshaller; import org.apache.isis.core.metamodel.adapter.oid.RootOid; +import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet; +import org.apache.isis.core.metamodel.spec.ObjectSpecId; +import org.apache.isis.core.metamodel.spec.ObjectSpecification; +import org.apache.isis.core.runtime.persistence.ObjectNotFoundException; +import org.apache.isis.core.runtime.persistence.PojoRecreationException; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; import org.apache.isis.viewer.restfulobjects.rendering.RendererContext; @@ -55,11 +61,50 @@ public final class OidUtils { private static ObjectAdapter getObjectAdapter( final RendererContext rendererContext, final String oidStrUnencoded) { - RootOid rootOid = RootOid.deString(oidStrUnencoded); + final RootOid rootOid = RootOid.deString(oidStrUnencoded); + final PersistenceSession ps = rendererContext.getPersistenceSession(); + final Object domainObject = domainObjectForAny(ps, rootOid); + + return ps.adapterFor(domainObject); + } - final PersistenceSession persistenceSession = rendererContext.getPersistenceSession(); + + private static Object domainObjectForAny(final PersistenceSession persistenceSession, RootOid rootOid) { + + final ObjectSpecId specId = rootOid.getObjectSpecId(); + final ObjectSpecification spec = persistenceSession.getServicesInjector() + .getSpecificationLoader() + .lookupBySpecId(specId); + if(spec == null) { + // eg "NONEXISTENT:123" + return null; + } - return persistenceSession.adapterForAny(rootOid); - } + if(spec.containsFacet(ViewModelFacet.class)) { + // this is a hack; the RO viewer when rendering the URL for the view model loses the "view model" indicator + // ("*") from the specId, meaning that the marshalling logic above in RootOidDefault.deString() creates an + // oid in the wrong state. The code below checks for this and recreates the oid with the current state of 'view model' + if(!rootOid.isViewModel()) { + rootOid = new RootOid(rootOid.getObjectSpecId(), rootOid.getIdentifier(), Oid.State.VIEWMODEL); + } + + try { + return persistenceSession.adapterFor(rootOid); + } catch(final ObjectNotFoundException ex) { + return null; + } catch(final PojoRecreationException ex) { + return null; + } + } else { + try { + final Object domainObject = persistenceSession.fetchPersistentPojoInTransaction(rootOid); + //[ISIS-1976] changed behavior: predicate was objectAdapter.isTransient(); + return persistenceSession.isTransient(domainObject) ? null : domainObject; + } catch(final ObjectNotFoundException ex) { + return null; + } + } + } + } diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DelegatingInvocationHandlerDefault.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DelegatingInvocationHandlerDefault.java index 3056749..9d23a36 100644 --- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DelegatingInvocationHandlerDefault.java +++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DelegatingInvocationHandlerDefault.java @@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.isis.applib.services.wrapper.events.InteractionEvent; +import org.apache.isis.commons.internal._Constants; import org.apache.isis.applib.services.wrapper.WrapperFactory; import org.apache.isis.applib.services.wrapper.WrapperFactory.ExecutionMode; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; @@ -56,8 +57,8 @@ public class DelegatingInvocationHandlerDefault<T> implements DelegatingInvocati try { equalsMethod = delegate.getClass().getMethod("equals", new Class[] { Object.class }); - hashCodeMethod = delegate.getClass().getMethod("hashCode", new Class[] {}); - toStringMethod = delegate.getClass().getMethod("toString", new Class[] {}); + hashCodeMethod = delegate.getClass().getMethod("hashCode", _Constants.emptyClasses); + toStringMethod = delegate.getClass().getMethod("toString", _Constants.emptyClasses); } catch (final NoSuchMethodException e) { // ///CLOVER:OFF throw new RuntimeException("An Object method could not be found: " + e.getMessage());