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/10 14:56:06 UTC

[isis] branch ISIS-1976-rethink-object-adapters updated (289890b -> 30842ab)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a change to branch ISIS-1976-rethink-object-adapters
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from 289890b  ISIS-1976: fixing NPE when represents-persistent is not recognized by the PM yet
     new a95d2e9  ISIS-1976: remove TypedOid; Oids: make cached hashes final and fix object contracts
     new 794344b  ISIS-1976: cleaning up some fixmes
     new 2a7dd9d  ISIS-1976: refactor OA-by-Oid supply responsibility into new interface
     new f1e233b  ISIS-1976: removing TransactionalClosures
     new d3c46e8  ISIS-1976: decouple viewmodel re-creation from PersistenceSession
     new 8ba3a7c  ISIS-1976: decouple lifecycle event posting from PersistenceSession
     new 73d4e28  ISIS-1976: remove some ObjectAdapter references from PS API
     new 30842ab  ISIS-1976: further remove OA references from PS API

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../applib/services/bookmark/BookmarkService.java  |   2 +-
 .../jaxbadapters/PersistentEntitiesAdapter.java    |   2 +-
 .../jaxbadapters/PersistentEntityAdapter.java      |   2 +-
 .../adapter/ObjectAdapterByIdProvider.java         |  86 ++++
 .../metamodel/adapter/ObjectAdapterProvider.java   |  62 ++-
 .../adapter/oid/ParentedCollectionOid.java         |  21 +-
 .../isis/core/metamodel/adapter/oid/RootOid.java   |  49 +-
 .../isis/core/metamodel/adapter/oid/TypedOid.java  |  30 --
 ...ctionInvocationFacetForDomainEventAbstract.java |  17 +-
 ...tySetterOrClearFacetForDomainEventAbstract.java |  14 +-
 .../PersistenceSessionServiceInternal.java         |  10 +-
 .../PersistenceSessionServiceInternalNoop.java     |  15 +-
 .../system/transaction/TransactionalClosure.java   |  25 -
 .../system/persistence/PersistenceSession4.java    | 544 ++++-----------------
 .../persistence/PersistenceSession4_Decouple.java  | 213 --------
 .../system/persistence/PersistenceSession5.java    | 525 ++++----------------
 .../PersistenceSessionServiceInternalDefault.java  |  43 +-
 .../AbstractIsisSessionTemplate.java               |  10 +-
 .../system/persistence/PersistenceSession.java     | 152 +++---
 .../system/persistence/PersistenceSessionBase.java |   9 -
 .../adaptermanager/ObjectAdapterContext.java       |  34 +-
 ... ObjectAdapterContext_DependencyInjection.java} |  53 +-
 ...ObjectAdapterContext_LifecycleEventSupport.java |  96 ++++
 .../ObjectAdapterContext_MementoSupport.java       |   2 +-
 ...tAdapterContext_ObjectAdapterByIdProvider.java} | 136 ++++--
 ...ObjectAdapterContext_ObjectAdapterProvider.java |  14 +
 .../ObjectAdapterContext_ObjectCreation.java       | 158 ++++++
 .../system/transaction/IsisTransactionManager.java |  24 +-
 .../transaction/TransactionalClosureAbstract.java  |  30 --
 .../TransactionalClosureWithReturn.java            |  25 -
 .../TransactionalClosureWithReturnAbstract.java    |  30 --
 .../resources/DomainObjectResourceServerside.java  |   2 +-
 .../restfulobjects/server/util/OidUtils.java       |  53 +-
 .../wicket/ConverterForObjectAdapter.java          |   6 +-
 .../wicket/ConverterForObjectAdapterMemento.java   |   9 +-
 .../wicket/model/models/EntityCollectionModel.java |  12 +-
 .../ui/pages/accmngt/register/RegisterPanel.java   |   6 +-
 .../DelegatingInvocationHandlerDefault.java        |   7 +-
 38 files changed, 988 insertions(+), 1540 deletions(-)
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterByIdProvider.java
 delete mode 100644 core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/TypedOid.java
 delete mode 100644 core/metamodel/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosure.java
 delete mode 100644 core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4_Decouple.java
 copy core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/{ObjectAdapterContext_NewIdentifier.java => ObjectAdapterContext_DependencyInjection.java} (64%)
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_LifecycleEventSupport.java
 rename core/{plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java => runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java} (72%)
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectCreation.java
 delete mode 100644 core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureAbstract.java
 delete mode 100644 core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturn.java
 delete mode 100644 core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturnAbstract.java


[isis] 02/08: ISIS-1976: cleaning up some fixmes

Posted by ah...@apache.org.
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 794344b7130dda88808c6ddd85b202917a390653
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 07:41:20 2018 +0200

    ISIS-1976: cleaning up some fixmes
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../system/persistence/PersistenceSession5_Decouple.java       | 10 ----------
 .../viewer/integration/wicket/ConverterForObjectAdapter.java   |  6 +-----
 .../integration/wicket/ConverterForObjectAdapterMemento.java   |  9 +++------
 3 files changed, 4 insertions(+), 21 deletions(-)

diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java
index 5568f4d..e40f9c3 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java
@@ -123,16 +123,6 @@ class PersistenceSession5_Decouple  {
             } catch(ObjectNotFoundException ex) {
                 throw ex; // just rethrow
             } catch(RuntimeException ex) {
-                
-                //FIXME[ISIS-1976] remove
-                System.err.println("------------------------------------------");
-                System.err.println("rootOid: "+rootOid.enString());
-                
-                ex.printStackTrace();
-                System.err.println("------------------------------------------");
-                //--
-
-                
                 throw new PojoRecreationException(rootOid, ex);
             }
         }
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
index a87b80d..bb9f53d 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
@@ -23,7 +23,6 @@ import java.util.Locale;
 
 import org.apache.wicket.util.convert.IConverter;
 
-import org.apache.isis.commons.internal.exceptions._Exceptions;
 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.RootOid;
@@ -46,10 +45,7 @@ public class ConverterForObjectAdapter implements IConverter<ObjectAdapter> {
     @Override
     public ObjectAdapter convertToObject(final String value, final Locale locale) {
         final RootOid rootOid = RootOid.deStringEncoded(value);
-        
-        //FIXME[ISIS-1976]
-        //return getPersistenceSession().lookupAdapterFor(rootOid);
-        throw _Exceptions.notImplemented();
+        return getPersistenceSession().adapterFor(rootOid);
     }
 
     /**
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
index 0abe928..7341f29 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
@@ -25,7 +25,6 @@ import com.google.common.base.Strings;
 
 import org.apache.wicket.util.convert.IConverter;
 
-import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.concurrency.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
@@ -54,12 +53,10 @@ public class ConverterForObjectAdapterMemento implements IConverter<ObjectAdapte
         if (Strings.isNullOrEmpty(value)) {
             return null;
         }
-        final Oid oid = RootOid.deStringEncoded(value);
+        final RootOid oid = RootOid.deStringEncoded(value);
         
-        //FIXME[ISIS-1976]
-        //final ObjectAdapter adapter = getPersistenceSession().lookupAdapterFor(oid);
-        //return ObjectAdapterMemento.createOrNull(adapter);
-        throw _Exceptions.notImplemented();
+        final ObjectAdapter adapter = getPersistenceSession().adapterFor(oid);
+        return ObjectAdapterMemento.createOrNull(adapter);
     }
 
     /**


[isis] 04/08: ISIS-1976: removing TransactionalClosures

Posted by ah...@apache.org.
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 f1e233be8e53ae344af56ff3dd9d764eb3338243
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 12:08:43 2018 +0200

    ISIS-1976: removing TransactionalClosures
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 ...ctionInvocationFacetForDomainEventAbstract.java |  17 +---
 ...tySetterOrClearFacetForDomainEventAbstract.java |  14 +--
 .../PersistenceSessionServiceInternal.java         |  10 +-
 .../PersistenceSessionServiceInternalNoop.java     |  15 ++-
 .../system/transaction/TransactionalClosure.java   |  25 -----
 .../system/persistence/PersistenceSession4.java    |  41 ++------
 .../system/persistence/PersistenceSession5.java    |  35 +------
 .../PersistenceSessionServiceInternalDefault.java  |  14 ++-
 .../AbstractIsisSessionTemplate.java               |  10 +-
 .../system/persistence/PersistenceSession.java     | 113 +++++++++++----------
 .../system/transaction/IsisTransactionManager.java |  24 +++--
 .../transaction/TransactionalClosureAbstract.java  |  30 ------
 .../TransactionalClosureWithReturn.java            |  25 -----
 .../TransactionalClosureWithReturnAbstract.java    |  30 ------
 .../ui/pages/accmngt/register/RegisterPanel.java   |   6 +-
 15 files changed, 128 insertions(+), 281 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index 997ef69..11ec2ef 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -83,7 +83,6 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.specloader.specimpl.MixedInMember2;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 import org.apache.isis.schema.ixn.v1.ActionInvocationDto;
 
 public abstract class ActionInvocationFacetForDomainEventAbstract
@@ -159,18 +158,10 @@ implements ImperativeFacet {
             final ObjectAdapter[] argumentAdapters,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
-        final ObjectAdapter[] holder = new ObjectAdapter[1];
-
-        getPersistenceSessionServiceInternal().executeWithinTransaction(
-                new TransactionalClosure(){
-                    @Override
-                    public void execute() {
-                        holder[0] = doInvoke(owningAction, targetAdapter, mixedInAdapter, argumentAdapters, interactionInitiatedBy);
-
-                    }
-                }
-                );
-        return holder[0];
+        final ObjectAdapter holder = 
+                getPersistenceSessionServiceInternal().executeWithinTransaction(()->
+                    doInvoke(owningAction, targetAdapter, mixedInAdapter, argumentAdapters, interactionInitiatedBy));
+        return holder;
     }
 
     ObjectAdapter doInvoke(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
index 84b5ee1..bb2df98 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
@@ -48,7 +48,6 @@ import org.apache.isis.core.metamodel.services.ixn.InteractionDtoServiceInternal
 import org.apache.isis.core.metamodel.services.persistsession.PersistenceSessionServiceInternal;
 import org.apache.isis.core.metamodel.services.publishing.PublishingServiceInternal;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 import org.apache.isis.schema.ixn.v1.PropertyEditDto;
 
 public abstract class PropertySetterOrClearFacetForDomainEventAbstract
@@ -161,16 +160,9 @@ extends SingleValueFacetAbstract<Class<? extends PropertyDomainEvent<?,?>>> {
             final ObjectAdapter newValueAdapter,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
-        getPersistenceSessionServiceInternal().executeWithinTransaction(
-                new TransactionalClosure(){
-                    @Override
-                    public void execute() {
-                        doSetOrClearProperty(style, owningProperty, targetAdapter, newValueAdapter, interactionInitiatedBy);
-                    }
-                }
-                );
-
-
+        getPersistenceSessionServiceInternal().executeWithinTransaction(()->{
+            doSetOrClearProperty(style, owningProperty, targetAdapter, newValueAdapter, interactionInitiatedBy);
+        });
 
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java
index 506ca6e..65509a9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternal.java
@@ -18,6 +18,7 @@ package org.apache.isis.core.metamodel.services.persistsession;
 
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.function.Supplier;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.query.Query;
@@ -29,7 +30,6 @@ import org.apache.isis.applib.services.xactn.TransactionState;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 
 public interface PersistenceSessionServiceInternal extends ObjectAdapterProvider.Delegating {
     
@@ -148,8 +148,6 @@ public interface PersistenceSessionServiceInternal extends ObjectAdapterProvider
     @Programmatic
     void remove(ObjectAdapter adapter);
 
-
-
     // -- allMatchingQuery, firstMatchingQuery
     /**
      * Provided by <tt>PersistenceSession</tt> when used by framework.
@@ -170,6 +168,10 @@ public interface PersistenceSessionServiceInternal extends ObjectAdapterProvider
     @Programmatic
     <T> ObjectAdapter firstMatchingQuery(Query<T> query);
 
-    void executeWithinTransaction(TransactionalClosure transactionalClosure);
+    @Programmatic
+    void executeWithinTransaction(Runnable task);
+    
+    @Programmatic
+    <T> T executeWithinTransaction(Supplier<T> task);
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java
index 86dfefb..3bc7c55 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/persistsession/PersistenceSessionServiceInternalNoop.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.metamodel.services.persistsession;
 
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.function.Supplier;
 
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
@@ -32,7 +33,6 @@ import org.apache.isis.applib.services.xactn.TransactionState;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 
 @DomainService(
         nature = NatureOfService.DOMAIN,
@@ -108,8 +108,15 @@ public class PersistenceSessionServiceInternalNoop implements PersistenceSession
     }
 
     @Override
-    public void executeWithinTransaction(TransactionalClosure transactionalClosure) {
-        transactionalClosure.execute();
+    public void executeWithinTransaction(Runnable task) {
+        //[ahuber] was task.run();
+        throw new UnsupportedOperationException("Not supported by this implementation of PersistenceSessionServiceInternal");
+    }
+    
+    @Override
+    public <T> T executeWithinTransaction(Supplier<T> task) {
+        //[ahuber] was return task.get();
+        throw new UnsupportedOperationException("Not supported by this implementation of PersistenceSessionServiceInternal");
     }
 
     @Override
@@ -150,4 +157,6 @@ public class PersistenceSessionServiceInternalNoop implements PersistenceSession
 
 
 
+
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosure.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosure.java
deleted file mode 100644
index ef88b55..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosure.java
+++ /dev/null
@@ -1,25 +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
- *
- *        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.transaction;
-
-public interface TransactionalClosure {
-
-    public void execute();
-}
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 390853a..8af6150 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
@@ -109,8 +109,6 @@ import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdap
 import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
 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;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosureWithReturn;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusCreateObjectCommand;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusDeleteObjectCommand;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.queries.PersistenceQueryFindAllInstancesProcessor;
@@ -381,12 +379,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final PersistenceQueryProcessor<? extends PersistenceQuery> processor = lookupProcessorFor(persistenceQuery);
 
         final List<ObjectAdapter> instances = transactionManager.executeWithinTransaction(
-                new TransactionalClosureWithReturn<List<ObjectAdapter>>() {
-                    @Override
-                    public List<ObjectAdapter> execute() {
-                        return processPersistenceQuery(processor, persistenceQuery);
-                    }
-                });
+                ()->processPersistenceQuery(processor, persistenceQuery) );
         final ObjectSpecification specification = persistenceQuery.getSpecification();
         final FreeStandingList results = new FreeStandingList(specification, instances);
         return adapterFor(results);
@@ -690,14 +683,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
 
         return transactionManager.executeWithinTransaction(
-                new TransactionalClosureWithReturn<ObjectAdapter>() {
-                    @Override
-                    public ObjectAdapter execute() {
+                ()-> {
                         LOG.debug("getObject; oid={}", oid);
 
                         final Object pojo = fetchPersistentPojo(oid);
                         return objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
-                    }
                 });
     }
 
@@ -809,11 +799,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     private void refreshRootInTransaction(final ObjectAdapter adapter) {
         Assert.assertTrue("only resolve object that is persistent", adapter, adapter.representsPersistent());
-        getTransactionManager().executeWithinTransaction(new TransactionalClosure() {
-
-            @Override
-            public void execute() {
-
+        getTransactionManager().executeWithinTransaction(()->{
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("resolveImmediately; oid={}", adapter.getOid().enString());
                 }
@@ -826,8 +812,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 }
 
                 refreshRoot(adapter);
-            }
-
         });
     }
 
@@ -891,16 +875,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             throw new NotPersistableException("Cannot persist services: " + adapter);
         }
 
-        getTransactionManager().executeWithinTransaction(new TransactionalClosure() {
-
-            @Override
-            public void execute() {
+        getTransactionManager().executeWithinTransaction(()->{
                 makePersistentTransactionAssumed(adapter);
-
-                // clear out the map of transient -> persistent
-                // already empty // PersistenceSession5.this.persistentByTransient.clear();
-            }
-
         });
     }
 
@@ -955,12 +931,9 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             return;
         }
         LOG.debug("destroyObject {}", adapter);
-        transactionManager.executeWithinTransaction(new TransactionalClosure() {
-            @Override
-            public void execute() {
-                final DestroyObjectCommand command = newDestroyObjectCommand(adapter);
-                transactionManager.addCommand(command);
-            }
+        transactionManager.executeWithinTransaction(()->{
+            final DestroyObjectCommand command = newDestroyObjectCommand(adapter);
+            transactionManager.addCommand(command);
         });
     }
 
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 0fae449..2e94fa3 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
@@ -109,8 +109,6 @@ import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdap
 import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
 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;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosureWithReturn;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusCreateObjectCommand;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.commands.DataNucleusDeleteObjectCommand;
 import org.apache.isis.objectstore.jdo.datanucleus.persistence.queries.PersistenceQueryFindAllInstancesProcessor;
@@ -379,12 +377,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final PersistenceQueryProcessor<? extends PersistenceQuery> processor = lookupProcessorFor(persistenceQuery);
 
         final List<ObjectAdapter> instances = transactionManager.executeWithinTransaction(
-                new TransactionalClosureWithReturn<List<ObjectAdapter>>() {
-                    @Override
-                    public List<ObjectAdapter> execute() {
-                        return processPersistenceQuery(processor, persistenceQuery);
-                    }
-                });
+                ()->processPersistenceQuery(processor, persistenceQuery) );
         final ObjectSpecification specification = persistenceQuery.getSpecification();
         final FreeStandingList results = new FreeStandingList(specification, instances);
         return adapterFor(results);
@@ -688,14 +681,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
 
         return transactionManager.executeWithinTransaction(
-                new TransactionalClosureWithReturn<ObjectAdapter>() {
-                    @Override
-                    public ObjectAdapter execute() {
+                ()-> {
                         LOG.debug("getObject; oid={}", oid);
 
                         final Object pojo = fetchPersistentPojo(oid);
                         return objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
-                    }
                 });
     }
 
@@ -807,11 +797,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     private void refreshRootInTransaction(final ObjectAdapter adapter) {
         Assert.assertTrue("only resolve object that is persistent", adapter, adapter.representsPersistent());
-        getTransactionManager().executeWithinTransaction(new TransactionalClosure() {
-
-            @Override
-            public void execute() {
-
+        getTransactionManager().executeWithinTransaction(()->{
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("resolveImmediately; oid={}", adapter.getOid().enString());
                 }
@@ -824,8 +810,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 }
 
                 refreshRoot(adapter);
-            }
-
         });
     }
 
@@ -889,16 +873,10 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             throw new NotPersistableException("Cannot persist services: " + adapter);
         }
 
-        getTransactionManager().executeWithinTransaction(new TransactionalClosure() {
-
-            @Override
-            public void execute() {
+        getTransactionManager().executeWithinTransaction(()->{
                 makePersistentTransactionAssumed(adapter);
-
                 // clear out the map of transient -> persistent
                 // already empty // PersistenceSession5.this.persistentByTransient.clear();
-            }
-
         });
     }
 
@@ -953,12 +931,9 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             return;
         }
         LOG.debug("destroyObject {}", adapter);
-        transactionManager.executeWithinTransaction(new TransactionalClosure() {
-            @Override
-            public void execute() {
+        transactionManager.executeWithinTransaction(()->{
                 final DestroyObjectCommand command = newDestroyObjectCommand(adapter);
                 transactionManager.addCommand(command);
-            }
         });
     }
 
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 5ee3b82..1d9f192 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
@@ -23,6 +23,7 @@ import static java.util.Optional.ofNullable;
 
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.function.Supplier;
 
 import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.annotation.DomainService;
@@ -46,7 +47,6 @@ import org.apache.isis.core.runtime.system.session.IsisSession;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 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;
 
 @DomainService(
         nature = NatureOfService.DOMAIN,
@@ -172,8 +172,13 @@ public class PersistenceSessionServiceInternalDefault implements PersistenceSess
     }
 
     @Override
-    public void executeWithinTransaction(TransactionalClosure transactionalClosure) {
-        getTransactionManager().executeWithinTransaction(transactionalClosure);
+    public void executeWithinTransaction(Runnable task) {
+        getTransactionManager().executeWithinTransaction(task);
+    }
+    
+    @Override
+    public <T> T executeWithinTransaction(Supplier<T> task) {
+        return getTransactionManager().executeWithinTransaction(task);
     }
 
     @Override
@@ -209,4 +214,7 @@ public class PersistenceSessionServiceInternalDefault implements PersistenceSess
     @javax.inject.Inject
     IsisSessionFactory isisSessionFactory;
 
+
+
+
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
index fc01c0f..ebe8947 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
@@ -23,7 +23,6 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSession;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 
 public abstract class AbstractIsisSessionTemplate {
 
@@ -57,11 +56,8 @@ public abstract class AbstractIsisSessionTemplate {
     protected void doExecute(final Object context) {
         final PersistenceSession persistenceSession = getPersistenceSession();
         final IsisTransactionManager transactionManager = getTransactionManager(persistenceSession);
-        transactionManager.executeWithinTransaction(new TransactionalClosure() {
-            @Override
-            public void execute() {
-                doExecuteWithTransaction(context);
-            }
+        transactionManager.executeWithinTransaction(()->{
+            doExecuteWithTransaction(context);
         });
     }
 
@@ -78,7 +74,7 @@ public abstract class AbstractIsisSessionTemplate {
 
     // //////////////////////////////////////
 
-//TODO[ISIS-1976] not used !?
+//FIXME[ISIS-1976] not used !?
 //    protected final ObjectAdapter adapterFor(final Object targetObject) {
 //        if(targetObject instanceof OidDto) {
 //            final OidDto oidDto = (OidDto) targetObject;
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 2354136..b7a22f5 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
@@ -46,43 +46,17 @@ extends
     TransactionalResource, 
     SessionScopedComponent {
 
-    // -- CONSTANTS
-
-    public static final String SERVICE_IDENTIFIER = "1";
-
-    /**
-     * @see #isFixturesInstalled()
-     */
-    public static final String INSTALL_FIXTURES_KEY = OptionHandlerFixtureAbstract.DATANUCLEUS_INSTALL_FIXTURES_KEY;
-    public static final boolean INSTALL_FIXTURES_DEFAULT = false;
-
-    //---
-
-    MementoRecreateObjectSupport mementoSupport();
-
-    ObjectAdapter adapterForAny(RootOid rootOid);
-    <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query);
-
-    // --
-
+    // -------------------------------------------------------------------------------------------------
+    // -- STABLE API (DRAFT)
+    // -------------------------------------------------------------------------------------------------
+    
+    void open();
     void close();
-
-    ObjectAdapter createTransientInstance(ObjectSpecification spec);
-
-    ObjectAdapter createViewModelInstance(ObjectSpecification spec, String memento);
-
-    void destroyObjectInTransaction(ObjectAdapter adapter);
-
-    void execute(List<PersistenceCommand> persistenceCommandList);
-    <T> ObjectAdapter firstMatchingQuery(final Query<T> query);
-
     boolean flush();
-
-    ObjectAdapter getAggregateRoot(ParentedCollectionOid collectionOid);
-
+    
     IsisConfiguration getConfiguration();
-
-    PersistenceManager getPersistenceManager();
+    IsisTransactionManager getTransactionManager();
+    ServicesInjector getServicesInjector();
     
     /**
      * @param pojo a persistable object
@@ -101,7 +75,13 @@ extends
     Object fetchPersistentPojo(RootOid rootOid);
     /**@since 2.0.0-M2*/
     Map<RootOid, Object> fetchPersistentPojos(List<RootOid> rootOids);
-
+    
+    
+    // -------------------------------------------------------------------------------------------------
+    // -- JDO SPECIFIC
+    // -------------------------------------------------------------------------------------------------
+    
+    PersistenceManager getPersistenceManager();
     /**
      * Convenient equivalent to {@code getPersistenceManager()}.
      * @return
@@ -109,19 +89,7 @@ extends
     default PersistenceManager pm() {
         return getPersistenceManager();
     }
-
-    ServicesInjector getServicesInjector();
-
-    IsisTransactionManager getTransactionManager();
-
-    Object instantiateAndInjectServices(ObjectSpecification spec);
-
-    boolean isFixturesInstalled();
-
-    Object lookup(Bookmark bookmark, FieldResetPolicy fieldResetPolicy);
-
-    void makePersistentInTransaction(ObjectAdapter adapter);
-
+    
     /**
      * Not type safe. For type-safe queries use <br/><br/> {@code pm().newNamedQuery(cls, queryName)}
      * @param cls
@@ -150,13 +118,56 @@ extends
     default <T> javax.jdo.Query newJdoQuery(Class<T> cls, String filter){
         return pm().newQuery(cls, filter);
     }
+    
+    // -------------------------------------------------------------------------------------------------
+    // -- API NOT STABLE YET - SUBJECT TO REFACTORING
+    // -------------------------------------------------------------------------------------------------
+    
+    // -- SERVICE SUPPORT
 
-    void open();
+    static final String SERVICE_IDENTIFIER = "1";
 
-    void refreshRoot(ObjectAdapter adapter);
+    // -- FIXTURE SUPPORT
+    
+    /**
+     * @see #isFixturesInstalled()
+     */
+    static final String INSTALL_FIXTURES_KEY = OptionHandlerFixtureAbstract.DATANUCLEUS_INSTALL_FIXTURES_KEY;
+    static final boolean INSTALL_FIXTURES_DEFAULT = false;
+    
+    boolean isFixturesInstalled();
+    
+    // -- MEMENTO SUPPORT
+    
+    MementoRecreateObjectSupport mementoSupport();
+    
+    // -- TODO remove ObjectAdapter references from API
+    
+    ObjectAdapter adapterForAny(RootOid rootOid);
+    <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query);
 
-    void resolve(Object parent);
+    ObjectAdapter createTransientInstance(ObjectSpecification spec);
 
+    ObjectAdapter createViewModelInstance(ObjectSpecification spec, String memento);
+
+    void destroyObjectInTransaction(ObjectAdapter adapter);
+
+    <T> ObjectAdapter firstMatchingQuery(final Query<T> query);
+    
+    ObjectAdapter getAggregateRoot(ParentedCollectionOid collectionOid);
+    
+    void makePersistentInTransaction(ObjectAdapter adapter);
+    
+    void refreshRoot(ObjectAdapter adapter);
     
+    // -- OTHERS
+    
+    void execute(List<PersistenceCommand> persistenceCommandList);
+
+    Object instantiateAndInjectServices(ObjectSpecification spec);
+
+    Object lookup(Bookmark bookmark, FieldResetPolicy fieldResetPolicy);
+
+    void resolve(Object parent);
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
index 108d458..b2d16cd 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
@@ -20,6 +20,10 @@
 package org.apache.isis.core.runtime.system.transaction;
 
 import java.util.UUID;
+import java.util.function.Supplier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
@@ -31,8 +35,6 @@ import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class IsisTransactionManager implements SessionScopedComponent {
 
@@ -126,18 +128,19 @@ public class IsisTransactionManager implements SessionScopedComponent {
      *  started here, or will ensure that an already-in-progress transaction cannot commit.
      * </p>
      */
-    public void executeWithinTransaction(final TransactionalClosure closure) {
-        executeWithinTransaction(null, closure);
+    public void executeWithinTransaction(final Runnable task) {
+        executeWithinTransaction(null, task);
     }
+    
     public void executeWithinTransaction(
             final Command existingCommandIfAny,
-            final TransactionalClosure closure) {
+            final Runnable task) {
         final boolean initiallyInTransaction = inTransaction();
         if (!initiallyInTransaction) {
             startTransaction(existingCommandIfAny);
         }
         try {
-            closure.execute();
+            task.run();
             if (!initiallyInTransaction) {
                 endTransaction();
             }
@@ -172,18 +175,19 @@ public class IsisTransactionManager implements SessionScopedComponent {
      *  started here, or will ensure that an already-in-progress transaction cannot commit.
      *  </p>
      */
-    public <Q> Q executeWithinTransaction(final TransactionalClosureWithReturn<Q> closure) {
-        return executeWithinTransaction(null, closure);
+    public <Q> Q executeWithinTransaction(final Supplier<Q> task) {
+        return executeWithinTransaction(null, task);
     }
+    
     public <Q> Q executeWithinTransaction(
             final Command existingCommandIfAny,
-            final TransactionalClosureWithReturn<Q> closure) {
+            final Supplier<Q> task) {
         final boolean initiallyInTransaction = inTransaction();
         if (!initiallyInTransaction) {
             startTransaction(existingCommandIfAny);
         }
         try {
-            final Q retVal = closure.execute();
+            final Q retVal = task.get();
             if (!initiallyInTransaction) {
                 endTransaction();
             }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureAbstract.java
deleted file mode 100644
index 20bbcdf..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureAbstract.java
+++ /dev/null
@@ -1,30 +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
- *
- *        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.transaction;
-
-/**
- * Not used by the framework, but provided for backward compatibility, eg by the (non-ASF) Isis addons.
- *
- * @deprecated - implement {@link TransactionalClosure} instead
- */
-@Deprecated
-public abstract class TransactionalClosureAbstract implements TransactionalClosure {
-
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturn.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturn.java
deleted file mode 100644
index ee2d0e5..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturn.java
+++ /dev/null
@@ -1,25 +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
- *
- *        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.transaction;
-
-public interface TransactionalClosureWithReturn<T> {
-
-    public T execute();
-}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturnAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturnAbstract.java
deleted file mode 100644
index 74caac1..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/TransactionalClosureWithReturnAbstract.java
+++ /dev/null
@@ -1,30 +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
- *
- *        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.transaction;
-
-/**
- * Not used by the framework, but provided for backward compatibility, eg by the (non-ASF) Isis addons.
- *
- * @deprecated - implement {@link TransactionalClosureWithReturn} instead
- */
-@Deprecated
-public abstract class TransactionalClosureWithReturnAbstract<T> implements TransactionalClosureWithReturn<T> {
-
-}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
index c41bd7b..2678c84 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
@@ -37,7 +37,6 @@ import org.apache.isis.applib.services.userreg.UserDetails;
 import org.apache.isis.applib.services.userreg.UserRegistrationService;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
-import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.pages.accmngt.AccountConfirmationMap;
 import org.apache.isis.viewer.wicket.ui.pages.accmngt.UsernameAvailableValidator;
@@ -131,12 +130,9 @@ public abstract class RegisterPanel extends GenericPanel<UserDetails> {
                             .getServicesInjector().lookupService(UserRegistrationService.class);
 
                     getIsisSessionFactory().getCurrentSession().getPersistenceSession().getTransactionManager()
-                    .executeWithinTransaction(new TransactionalClosure() {
-                        @Override
-                        public void execute() {
+                    .executeWithinTransaction(() -> {
                             userRegistrationService.registerUser(userDetails);
                             removeAccountConfirmation();
-                        }
                     });
                 }
             });


[isis] 01/08: ISIS-1976: remove TypedOid; Oids: make cached hashes final and fix object contracts

Posted by ah...@apache.org.
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 a95d2e90608145acabc5d17763ebc2a3655a0fcf
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 07:28:47 2018 +0200

    ISIS-1976: remove TypedOid; Oids: make cached hashes final and fix
    object contracts
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../adapter/oid/ParentedCollectionOid.java         | 21 ++++------
 .../isis/core/metamodel/adapter/oid/RootOid.java   | 49 +++++++---------------
 .../isis/core/metamodel/adapter/oid/TypedOid.java  | 30 -------------
 3 files changed, 22 insertions(+), 78 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/ParentedCollectionOid.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/ParentedCollectionOid.java
index 765b034..9f463f6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/ParentedCollectionOid.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/ParentedCollectionOid.java
@@ -21,8 +21,7 @@ package org.apache.isis.core.metamodel.adapter.oid;
 
 import java.io.IOException;
 import java.io.Serializable;
-
-import com.google.common.base.Objects;
+import java.util.Objects;
 
 import org.apache.isis.core.commons.encoding.DataInputExtended;
 import org.apache.isis.core.commons.encoding.DataOutputExtended;
@@ -40,7 +39,7 @@ public final class ParentedCollectionOid implements Serializable, Oid {
     private final static OidMarshaller OID_MARSHALLER = OidMarshaller.INSTANCE;
 
     private final String name;
-    private int cachedHashCode;
+    private final int hashCode;
 
     private final RootOid parentOid;
 
@@ -56,7 +55,7 @@ public final class ParentedCollectionOid implements Serializable, Oid {
         Assert.assertNotNull("rootOid required", rootOid);
         this.parentOid = rootOid;
         this.name = name;
-        cacheState();
+        this.hashCode = calculateHash();
     }
 
 
@@ -122,6 +121,7 @@ public final class ParentedCollectionOid implements Serializable, Oid {
     private ParentedCollectionOid(ParentedCollectionOid oid) throws IOException {
         this.parentOid = oid.getRootOid();
         this.name = oid.name;
+        this.hashCode = calculateHash();
     }
 
 
@@ -169,25 +169,20 @@ public final class ParentedCollectionOid implements Serializable, Oid {
     }
 
     public boolean equals(final ParentedCollectionOid other) {
-        return Objects.equal(other.getRootOid(), getRootOid()) && Objects.equal(other.name, name);
+        return Objects.equals(other.getRootOid(), getRootOid()) && Objects.equals(other.name, name);
     }
 
 
     @Override
     public int hashCode() {
-        cacheState();
-        return cachedHashCode;
+        return hashCode;
     }
 
-    private void cacheState() {
-        int hashCode = 17;
-        hashCode = 37 * hashCode + getRootOid().hashCode();
-        hashCode = 37 * hashCode + name.hashCode();
-        cachedHashCode = hashCode;
+    private int calculateHash() {
+        return Objects.hash(getRootOid(), name);
     }
 
 
-
     // /////////////////////////////////////////////////////////
     // asPersistent
     // /////////////////////////////////////////////////////////
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/RootOid.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/RootOid.java
index 7cbb26d..3836542 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/RootOid.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/RootOid.java
@@ -21,11 +21,7 @@ package org.apache.isis.core.metamodel.adapter.oid;
 
 import java.io.IOException;
 import java.io.Serializable;
-
-import com.google.common.base.Objects;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.Objects;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.commons.encoding.DataInputExtended;
@@ -36,25 +32,20 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.schema.common.v1.BookmarkObjectState;
 import org.apache.isis.schema.common.v1.OidDto;
 
-public class RootOid implements TypedOid, Serializable {
+public class RootOid implements Oid, Serializable {
 
     // -- fields
-    private final static Logger LOG = LoggerFactory.getLogger(RootOid.class);
-
-    private static final long serialVersionUID = 1L;
-
+    private final static long serialVersionUID = 1L;
     private final static OidMarshaller OID_MARSHALLER = OidMarshaller.INSTANCE;
 
     private final ObjectSpecId objectSpecId;
     private final String identifier;
     private final State state;
-
+    private final int hashCode;
 
     // not part of equality check
     private Version version;
 
-    private int cachedHashCode;
-
 
     // -- Constructor, factory methods
     public static RootOid createTransient(final ObjectSpecId objectSpecId, final String identifier) {
@@ -130,15 +121,9 @@ public class RootOid implements TypedOid, Serializable {
         this.identifier = identifier;
         this.state = state;
         this.version = version;
-        initialized();
-    }
-
-    private void initialized() {
-        cacheState();
+        this.hashCode = calculateHash();
     }
 
-
-
     // -- Encodeable
     public RootOid(final DataInputExtended input) throws IOException {
         final String oidStr = input.readUTF();
@@ -147,7 +132,7 @@ public class RootOid implements TypedOid, Serializable {
         this.identifier = oid.identifier;
         this.state = oid.state;
         this.version = oid.version;
-        cacheState();
+        this.hashCode = calculateHash();
     }
 
     @Override
@@ -155,9 +140,6 @@ public class RootOid implements TypedOid, Serializable {
         output.writeUTF(enString());
     }
 
-
-
-
     // -- deString'able, enString
     public static RootOid deStringEncoded(final String urlEncodedOidStr) {
         final String oidStr = UrlDecoderUtil.urlDecode(urlEncodedOidStr);
@@ -180,7 +162,6 @@ public class RootOid implements TypedOid, Serializable {
 
 
     // -- Properties
-    @Override
     public ObjectSpecId getObjectSpecId() {
         return objectSpecId;
     }
@@ -244,11 +225,8 @@ public class RootOid implements TypedOid, Serializable {
 
     // -- equals, hashCode
 
-    private void cacheState() {
-        cachedHashCode = 17;
-        cachedHashCode = 37 * cachedHashCode + objectSpecId.hashCode();
-        cachedHashCode = 37 * cachedHashCode + identifier.hashCode();
-        cachedHashCode = 37 * cachedHashCode + (isTransient() ? 0 : 1);
+    private int calculateHash() {
+        return Objects.hash(objectSpecId, identifier, state);
     }
 
     @Override
@@ -266,12 +244,14 @@ public class RootOid implements TypedOid, Serializable {
     }
 
     public boolean equals(final RootOid other) {
-        return Objects.equal(objectSpecId, other.getObjectSpecId()) && Objects.equal(identifier, other.getIdentifier()) && Objects.equal(isTransient(), other.isTransient());
+        return Objects.equals(objectSpecId, other.getObjectSpecId()) && 
+                Objects.equals(identifier, other.getIdentifier()) && 
+                Objects.equals(state, other.state);
     }
 
     @Override
     public int hashCode() {
-        return cachedHashCode;
+        return hashCode;
     }
 
 
@@ -284,11 +264,10 @@ public class RootOid implements TypedOid, Serializable {
 
     // -- ROOT-ID SUPPORT FOR VALUE
     
-    private RootOid() { identifier=null; objectSpecId=null; state=null; };
+    private RootOid() { identifier=null; objectSpecId=null; state=null; hashCode=0;};
     
     private static final RootOid VALUE_OID = new RootOid() {
-        private static final long serialVersionUID = 1L;
-
+        private static final long serialVersionUID = 2L;
         @Override
         public boolean isValue() {
             return true;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/TypedOid.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/TypedOid.java
deleted file mode 100644
index 141466e..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/TypedOid.java
+++ /dev/null
@@ -1,30 +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
- *
- *        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.metamodel.adapter.oid;
-
-import org.apache.isis.core.metamodel.spec.ObjectSpecId;
-
-/**
- * @deprecated  - for backward compatibility with addons.
- */
-@Deprecated
-public interface TypedOid extends Oid {
-    ObjectSpecId getObjectSpecId();
-}


[isis] 06/08: ISIS-1976: decouple lifecycle event posting from PersistenceSession

Posted by ah...@apache.org.
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 8ba3a7cdc4ed556baf1db4e81b25f96bc6739443
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 13:24:19 2018 +0200

    ISIS-1976: decouple lifecycle event posting from PersistenceSession
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../system/persistence/PersistenceSession4.java    |  97 ++-----------
 .../system/persistence/PersistenceSession5.java    | 107 ++------------
 .../system/persistence/PersistenceSession.java     |   3 +-
 .../system/persistence/PersistenceSessionBase.java |   9 --
 .../adaptermanager/ObjectAdapterContext.java       |  32 ++++-
 ...ObjectAdapterContext_LifecycleEventSupport.java |  96 +++++++++++++
 .../ObjectAdapterContext_ObjectCreation.java       | 158 +++++++++++++++++++++
 .../ObjectAdapterContext_ObjectReCreation.java     |  72 ----------
 8 files changed, 298 insertions(+), 276 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 1acd10d..35230c5 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
@@ -441,95 +441,14 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     @Override
     public ObjectAdapter createTransientInstance(final ObjectSpecification objectSpec) {
-        return createInstance(objectSpec, Variant.TRANSIENT, null);
+        return objectAdapterContext.newInstance(objectSpec);
     }
 
     @Override
     public ObjectAdapter createViewModelInstance(final ObjectSpecification objectSpec, final String memento) {
-        return createInstance(objectSpec, Variant.VIEW_MODEL, memento);
+        return objectAdapterContext.recreateInstance(objectSpec, memento);
     }
 
-    private ObjectAdapter createInstance(
-            final ObjectSpecification spec,
-            final Variant variant,
-            final String memento) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("creating {} instance of {}", variant, spec);
-        }
-        final Object pojo;
-
-        if(variant == Variant.VIEW_MODEL) {
-            pojo = objectAdapterContext.recreateViewModel(spec, memento);
-        } else {
-            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
-        }
-
-        final ObjectAdapter adapter = adapterFor(pojo);
-        return initializePropertiesAndDoCallback(adapter);
-    }
-
-    private ObjectAdapter initializePropertiesAndDoCallback(final ObjectAdapter adapter) {
-
-        // initialize new object
-        final List<ObjectAssociation> fields = adapter.getSpecification().getAssociations(Contributed.EXCLUDED);
-        for (ObjectAssociation field : fields) {
-            field.toDefault(adapter);
-        }
-        final Object pojo = adapter.getObject();
-        servicesInjector.injectServicesInto(pojo);
-
-        CallbackFacet.Util.callCallback(adapter, CreatedCallbackFacet.class);
-
-        if (Command.class.isAssignableFrom(pojo.getClass())) {
-
-            // special case... the command object is created while the transaction is being started and before
-            // the event bus service is initialized (nb: we initialize services *within* a transaction).  To resolve
-            // this catch-22 situation, we simply suppress the posting of this event for this domain class.
-
-            // this seems the least unpleasant of the various options available:
-            // * we could have put a check in the EventBusService to ignore the post if not yet initialized;
-            //   however this might hide other genuine errors
-            // * we could have used the thread-local in JdoStateManagerForIsis and the "skip(...)" hook in EventBusServiceJdo
-            //   to have this event be skipped; but that seems like co-opting some other design
-            // * we could have the transaction initialize the EventBusService as a "special case" before creating the Command;
-            //   but then do we worry about it being re-init'd later by the ServicesInitializer?
-
-            // so, doing it this way is this simplest, least obscure.
-
-            if(LOG.isDebugEnabled()) {
-                LOG.debug("Skipping postEvent for creation of Command pojo");
-            }
-
-        } else {
-            postLifecycleEventIfRequired(adapter, CreatedLifecycleEventFacet.class);
-        }
-
-        return adapter;
-    }
-
-
-    // -- helper: postEvent
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    void postLifecycleEventIfRequired(
-            final ObjectAdapter adapter,
-            final Class<? extends LifecycleEventFacet> lifecycleEventFacetClass) {
-        final LifecycleEventFacet facet = adapter.getSpecification().getFacet(lifecycleEventFacetClass);
-        if(facet != null) {
-            final Class<? extends AbstractLifecycleEvent<?>> eventType = facet.getEventType();
-            final Object instance = InstanceUtil.createInstance(eventType);
-            final Object pojo = adapter.getObject();
-            postEvent((AbstractLifecycleEvent) instance, pojo);
-        }
-    }
-
-    void postEvent(final AbstractLifecycleEvent<Object> event, final Object pojo) {
-        event.setSource(pojo);
-        eventBusService.post(event);
-    }
-
-
-
 
     // -- fixture installation
 
@@ -1021,7 +940,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         changedObjectsServiceInternal.enlistDeleting(adapter);
 
         CallbackFacet.Util.callCallback(adapter, RemovingCallbackFacet.class);
-        postLifecycleEventIfRequired(adapter, RemovingLifecycleEventFacet.class);
+        objectAdapterContext.postLifecycleEventIfRequired(adapter, RemovingLifecycleEventFacet.class);
     }
 
     @Override
@@ -1083,7 +1002,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 adapter = objectAdapterContext.addRecreatedPojoToCache(originalOid, pojo);
 
                 CallbackFacet.Util.callCallback(adapter, LoadedCallbackFacet.class);
-                postLifecycleEventIfRequired(adapter, LoadedLifecycleEventFacet.class);
+                objectAdapterContext.postLifecycleEventIfRequired(adapter, LoadedLifecycleEventFacet.class);
             }
         
             newAdapter = adapter;
@@ -1130,7 +1049,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             // persisting
             // previously this was performed in the DataNucleusSimplePersistAlgorithm.
             CallbackFacet.Util.callCallback(adapter, PersistingCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, PersistingLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, PersistingLifecycleEventFacet.class);
 
         } else {
             // updating
@@ -1162,7 +1081,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             objectAdapterContext.remapAsPersistent(adapter, persistentOid, this);
 
             CallbackFacet.Util.callCallback(adapter, PersistedCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
 
             changedObjectsServiceInternal.enlistCreated(adapter);
 
@@ -1171,7 +1090,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             // the callback and transaction.enlist are done in the preDirty callback
             // (can't be done here, as the enlist requires to capture the 'before' values)
             CallbackFacet.Util.callCallback(adapter, UpdatedCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, UpdatedLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, UpdatedLifecycleEventFacet.class);
         }
 
         Version versionIfAny = getVersionIfAny(pojo);
@@ -1215,7 +1134,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         if(!wasAlreadyEnlisted) {
             // prevent an infinite loop... don't call the 'updating()' callback on this object if we have already done so
             CallbackFacet.Util.callCallback(adapter, UpdatingCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class);
         }
 
         ensureRootObject(pojo);
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 3441cf0..6255c81 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
@@ -21,8 +21,6 @@ package org.apache.isis.core.runtime.system.persistence;
 import static java.util.Objects.requireNonNull;
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
 
-import java.lang.reflect.Array;
-import java.lang.reflect.Modifier;
 import java.sql.Timestamp;
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -48,7 +46,6 @@ import org.datanucleus.identity.DatastoreIdImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.applib.events.lifecycle.AbstractLifecycleEvent;
 import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
@@ -58,7 +55,6 @@ 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.commons.factory.InstanceUtil;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
@@ -70,9 +66,6 @@ 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.object.callbacks.CallbackFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedCallbackFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.LifecycleEventFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedCallbackFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.PersistedCallbackFacet;
@@ -91,8 +84,6 @@ 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.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.runtime.persistence.FixturesInstalledFlag;
 import org.apache.isis.core.runtime.persistence.NotPersistableException;
 import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
@@ -439,96 +430,14 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     @Override
     public ObjectAdapter createTransientInstance(final ObjectSpecification objectSpec) {
-        return createInstance(objectSpec, Variant.TRANSIENT, null);
+        return objectAdapterContext.newInstance(objectSpec);
     }
 
     @Override
     public ObjectAdapter createViewModelInstance(final ObjectSpecification objectSpec, final String memento) {
-        return createInstance(objectSpec, Variant.VIEW_MODEL, memento);
+        return objectAdapterContext.recreateInstance(objectSpec, memento);
     }
 
-    private ObjectAdapter createInstance(
-            final ObjectSpecification spec,
-            final Variant variant,
-            final String memento) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("creating {} instance of {}", variant, spec);
-        }
-        final Object pojo;
-
-        if(variant == Variant.VIEW_MODEL) {
-            pojo = objectAdapterContext.recreateViewModel(spec, memento);
-        } else {
-            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
-
-        }
-
-        final ObjectAdapter adapter = adapterFor(pojo);
-        return initializePropertiesAndDoCallback(adapter);
-    }
-
-    private ObjectAdapter initializePropertiesAndDoCallback(final ObjectAdapter adapter) {
-
-        // initialize new object
-        final List<ObjectAssociation> fields = adapter.getSpecification().getAssociations(Contributed.EXCLUDED);
-        for (ObjectAssociation field : fields) {
-            field.toDefault(adapter);
-        }
-        final Object pojo = adapter.getObject();
-        servicesInjector.injectServicesInto(pojo);
-
-        CallbackFacet.Util.callCallback(adapter, CreatedCallbackFacet.class);
-
-        if (Command.class.isAssignableFrom(pojo.getClass())) {
-
-            // special case... the command object is created while the transaction is being started and before
-            // the event bus service is initialized (nb: we initialize services *within* a transaction).  To resolve
-            // this catch-22 situation, we simply suppress the posting of this event for this domain class.
-
-            // this seems the least unpleasant of the various options available:
-            // * we could have put a check in the EventBusService to ignore the post if not yet initialized;
-            //   however this might hide other genuine errors
-            // * we could have used the thread-local in JdoStateManagerForIsis and the "skip(...)" hook in EventBusServiceJdo
-            //   to have this event be skipped; but that seems like co-opting some other design
-            // * we could have the transaction initialize the EventBusService as a "special case" before creating the Command;
-            //   but then do we worry about it being re-init'd later by the ServicesInitializer?
-
-            // so, doing it this way is this simplest, least obscure.
-
-            if(LOG.isDebugEnabled()) {
-                LOG.debug("Skipping postEvent for creation of Command pojo");
-            }
-
-        } else {
-            postLifecycleEventIfRequired(adapter, CreatedLifecycleEventFacet.class);
-        }
-
-        return adapter;
-    }
-
-
-    // -- helper: postEvent
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    void postLifecycleEventIfRequired(
-            final ObjectAdapter adapter,
-            final Class<? extends LifecycleEventFacet> lifecycleEventFacetClass) {
-        final LifecycleEventFacet facet = adapter.getSpecification().getFacet(lifecycleEventFacetClass);
-        if(facet != null) {
-            final Class<? extends AbstractLifecycleEvent<?>> eventType = facet.getEventType();
-            final Object instance = InstanceUtil.createInstance(eventType);
-            final Object pojo = adapter.getObject();
-            postEvent((AbstractLifecycleEvent) instance, pojo);
-        }
-    }
-
-    void postEvent(final AbstractLifecycleEvent<Object> event, final Object pojo) {
-        event.setSource(pojo);
-        eventBusService.post(event);
-    }
-
-
-
 
     // -- fixture installation
 
@@ -1017,7 +926,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         changedObjectsServiceInternal.enlistDeleting(adapter);
 
         CallbackFacet.Util.callCallback(adapter, RemovingCallbackFacet.class);
-        postLifecycleEventIfRequired(adapter, RemovingLifecycleEventFacet.class);
+        objectAdapterContext.postLifecycleEventIfRequired(adapter, RemovingLifecycleEventFacet.class);
     }
 
     @Override
@@ -1079,7 +988,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 adapter = objectAdapterContext.addRecreatedPojoToCache(originalOid, pojo);
 
                 CallbackFacet.Util.callCallback(adapter, LoadedCallbackFacet.class);
-                postLifecycleEventIfRequired(adapter, LoadedLifecycleEventFacet.class);
+                objectAdapterContext.postLifecycleEventIfRequired(adapter, LoadedLifecycleEventFacet.class);
             }
         
             newAdapter = adapter;
@@ -1126,7 +1035,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             // persisting
             // previously this was performed in the DataNucleusSimplePersistAlgorithm.
             CallbackFacet.Util.callCallback(adapter, PersistingCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, PersistingLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, PersistingLifecycleEventFacet.class);
 
         } else {
             // updating
@@ -1158,7 +1067,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             objectAdapterContext.remapAsPersistent(adapter, persistentOid, this);
 
             CallbackFacet.Util.callCallback(adapter, PersistedCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, PersistedLifecycleEventFacet.class);
 
             changedObjectsServiceInternal.enlistCreated(adapter);
 
@@ -1167,7 +1076,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             // the callback and transaction.enlist are done in the preDirty callback
             // (can't be done here, as the enlist requires to capture the 'before' values)
             CallbackFacet.Util.callCallback(adapter, UpdatedCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, UpdatedLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, UpdatedLifecycleEventFacet.class);
         }
 
         Version versionIfAny = getVersionIfAny(pojo);
@@ -1211,7 +1120,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         if(!wasAlreadyEnlisted) {
             // prevent an infinite loop... don't call the 'updating()' callback on this object if we have already done so
             CallbackFacet.Util.callCallback(adapter, UpdatingCallbackFacet.class);
-            postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class);
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class);
         }
 
         ensureRootObject(pojo);
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 8f3967f..af0a2e8 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
@@ -53,6 +53,7 @@ extends
     void open();
     void close();
     boolean flush();
+    void resolve(Object parent);
     
     IsisConfiguration getConfiguration();
     IsisTransactionManager getTransactionManager();
@@ -166,6 +167,6 @@ extends
 
     Object lookup(Bookmark bookmark, FieldResetPolicy fieldResetPolicy);
 
-    void resolve(Object parent);
+    
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java
index f597cc5..21f1e31 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionBase.java
@@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
 import org.apache.isis.applib.services.clock.ClockService;
 import org.apache.isis.applib.services.command.CommandContext;
 import org.apache.isis.applib.services.command.spi.CommandService;
-import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.applib.services.metrics.MetricsService;
@@ -67,7 +66,6 @@ abstract class PersistenceSessionBase implements PersistenceSession {
     protected final CommandService commandService;
 
     protected final InteractionContext interactionContext;
-    protected final EventBusService eventBusService ;
     protected final ChangedObjectsServiceInternal changedObjectsServiceInternal;
     protected final FactoryService factoryService;
     protected final MetricsService metricsService;
@@ -122,7 +120,6 @@ abstract class PersistenceSessionBase implements PersistenceSession {
         this.commandContext = lookupService(CommandContext.class);
         this.commandService = lookupService(CommandService.class);
         this.interactionContext = lookupService(InteractionContext.class);
-        this.eventBusService = lookupService(EventBusService.class);
         this.changedObjectsServiceInternal = lookupService(ChangedObjectsServiceInternal.class);
         this.metricsService = lookupService(MetricsService.class);
         this.factoryService = lookupService(FactoryService.class);
@@ -184,11 +181,6 @@ abstract class PersistenceSessionBase implements PersistenceSession {
         PERSISTENT
     }
 
-    protected enum Variant {
-        TRANSIENT,
-        VIEW_MODEL
-    }
-
     protected enum State {
         NOT_INITIALIZED, OPEN, CLOSED
     }
@@ -264,5 +256,4 @@ abstract class PersistenceSessionBase implements PersistenceSession {
         return new ToString(this).toString();
     }
 
-
 }
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 efff6cc..d4ac548 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,6 +22,8 @@ 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;
 
@@ -36,7 +38,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.Version;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.LifecycleEventFacet;
 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;
@@ -135,7 +137,8 @@ public class ObjectAdapterContext {
     private final ObjectAdapterContext_NewIdentifier newIdentifierMixin;
     private final ObjectAdapterContext_ObjectAdapterByIdProvider objectAdapterByIdProviderMixin;
     private final ObjectAdapterContext_DependencyInjection dependencyInjectionMixin;
-    private final ObjectAdapterContext_ObjectReCreation objectReCreationMixin;
+    private final ObjectAdapterContext_ObjectCreation objectReCreationMixin;
+    private final ObjectAdapterContext_LifecycleEventSupport lifecycleEventMixin;
     
     private ObjectAdapterContext(
             ServicesInjector servicesInjector, 
@@ -151,7 +154,8 @@ 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_ObjectReCreation(this, persistenceSession);
+        this.objectReCreationMixin = new ObjectAdapterContext_ObjectCreation(this, persistenceSession);
+        this.lifecycleEventMixin = new ObjectAdapterContext_LifecycleEventSupport(this, persistenceSession);
         
         this.persistenceSession = persistenceSession;
         this.servicesInjector = servicesInjector;
@@ -347,10 +351,22 @@ public class ObjectAdapterContext {
         return mementoSupportMixin;
     }
     
-    // -- OBJECT RECREATION SUPPORT
+    // -- 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 Object recreateViewModel(final ObjectSpecification spec, final String memento) {
-        return objectReCreationMixin.recreateViewModel(spec, memento);
+    public void postLifecycleEventIfRequired(
+            final ObjectAdapter adapter,
+            final Class<? extends LifecycleEventFacet> lifecycleEventFacetClass) {
+        lifecycleEventMixin.postLifecycleEventIfRequired(adapter, lifecycleEventFacetClass);
     }
     
     // ------------------------------------------------------------------------------------------------
@@ -493,4 +509,8 @@ public class ObjectAdapterContext {
 
 
 
+
+
+
+
 }
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_LifecycleEventSupport.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_LifecycleEventSupport.java
new file mode 100644
index 0000000..217ca05
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_LifecycleEventSupport.java
@@ -0,0 +1,96 @@
+/*
+ *  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 java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.events.lifecycle.AbstractLifecycleEvent;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedCallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.LifecycleEventFacet;
+import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+/**
+ * package private mixin for ObjectAdapterContext
+ * <p>
+ * Responsibility: provides life-cycle event post support
+ * </p> 
+ * @since 2.0.0-M2
+ */
+@SuppressWarnings("unused")
+class ObjectAdapterContext_LifecycleEventSupport {
+    
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_LifecycleEventSupport.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector;
+    private final SpecificationLoader specificationLoader;
+    private final EventBusService eventBusService; 
+    
+    
+    ObjectAdapterContext_LifecycleEventSupport(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+        this.specificationLoader = servicesInjector.getSpecificationLoader();
+        this.eventBusService = servicesInjector.lookupService(EventBusService.class);
+    }
+    
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    void postLifecycleEventIfRequired(
+            final ObjectAdapter adapter,
+            final Class<? extends LifecycleEventFacet> lifecycleEventFacetClass) {
+        final LifecycleEventFacet facet = adapter.getSpecification().getFacet(lifecycleEventFacetClass);
+        if(facet != null) {
+            final Class<? extends AbstractLifecycleEvent<?>> eventType = facet.getEventType();
+            final Object instance = InstanceUtil.createInstance(eventType);
+            final Object pojo = adapter.getObject();
+            postEvent((AbstractLifecycleEvent) instance, pojo);
+        }
+    }
+    
+    //  -- HELPER
+    
+    private void postEvent(final AbstractLifecycleEvent<Object> event, final Object pojo) {
+        if(eventBusService!=null) {
+            event.setSource(pojo);
+            eventBusService.post(event);
+        }
+    }
+
+    
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectCreation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectCreation.java
new file mode 100644
index 0000000..b50a42e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectCreation.java
@@ -0,0 +1,158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.runtime.system.persistence.adaptermanager;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.events.lifecycle.AbstractLifecycleEvent;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedCallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.LifecycleEventFacet;
+import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+/**
+ * package private mixin for ObjectAdapterContext
+ * <p>
+ * Responsibility: re-creates domain object instances  
+ * </p> 
+ * @since 2.0.0-M2
+ */
+@SuppressWarnings("unused")
+class ObjectAdapterContext_ObjectCreation {
+    
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_ObjectCreation.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector;
+    private final SpecificationLoader specificationLoader;
+    
+    ObjectAdapterContext_ObjectCreation(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+        this.specificationLoader = servicesInjector.getSpecificationLoader();
+    }
+    
+    public ObjectAdapter newInstance(ObjectSpecification objectSpec) {
+        return newInstance(objectSpec, Variant.TRANSIENT, null);
+    }
+
+    public ObjectAdapter recreateInstance(ObjectSpecification objectSpec, @Nullable String memento) {
+        return newInstance(objectSpec, Variant.VIEW_MODEL, memento);
+    }
+    
+    //  -- HELPER
+    
+    private enum Variant {
+        TRANSIENT,
+        VIEW_MODEL
+    }
+    
+    private ObjectAdapter newInstance(ObjectSpecification spec, Variant variant, String memento) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("creating {} instance of {}", variant, spec);
+        }
+        final Object pojo;
+
+        if(variant == Variant.VIEW_MODEL) {
+            pojo = recreateViewModel(spec, memento);
+        } else {
+            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
+
+        }
+
+        final ObjectAdapter adapter = objectAdapterContext.getObjectAdapterProvider().adapterFor(pojo);
+        return initializePropertiesAndDoCallback(adapter);
+    }
+    
+    private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
+        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
+        if(facet == null) {
+            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
+        }
+
+        final Object viewModelPojo;
+        if(facet.getRecreationMechanism().isInitializes()) {
+            viewModelPojo = objectAdapterContext.instantiateAndInjectServices(spec);
+            facet.initialize(viewModelPojo, memento);
+        } else {
+            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
+        }
+        return viewModelPojo;
+    }
+    
+    private ObjectAdapter initializePropertiesAndDoCallback(final ObjectAdapter adapter) {
+
+        // initialize new object
+        final List<ObjectAssociation> fields = adapter.getSpecification().getAssociations(Contributed.EXCLUDED);
+        for (ObjectAssociation field : fields) {
+            field.toDefault(adapter);
+        }
+        final Object pojo = adapter.getObject();
+        servicesInjector.injectServicesInto(pojo);
+
+        CallbackFacet.Util.callCallback(adapter, CreatedCallbackFacet.class);
+
+        if (Command.class.isAssignableFrom(pojo.getClass())) {
+
+            // special case... the command object is created while the transaction is being started and before
+            // the event bus service is initialized (nb: we initialize services *within* a transaction).  To resolve
+            // this catch-22 situation, we simply suppress the posting of this event for this domain class.
+
+            // this seems the least unpleasant of the various options available:
+            // * we could have put a check in the EventBusService to ignore the post if not yet initialized;
+            //   however this might hide other genuine errors
+            // * we could have used the thread-local in JdoStateManagerForIsis and the "skip(...)" hook in EventBusServiceJdo
+            //   to have this event be skipped; but that seems like co-opting some other design
+            // * we could have the transaction initialize the EventBusService as a "special case" before creating the Command;
+            //   but then do we worry about it being re-init'd later by the ServicesInitializer?
+
+            // so, doing it this way is this simplest, least obscure.
+
+            if(LOG.isDebugEnabled()) {
+                LOG.debug("Skipping postEvent for creation of Command pojo");
+            }
+
+        } else {
+            objectAdapterContext.postLifecycleEventIfRequired(adapter, CreatedLifecycleEventFacet.class);
+        }
+
+        return adapter;
+    }
+
+    
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java
deleted file mode 100644
index cb276ac..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java
+++ /dev/null
@@ -1,72 +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
- *
- *        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.metamodel.facets.object.viewmodel.ViewModelFacet;
-import org.apache.isis.core.metamodel.services.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
-
-/**
- * package private mixin for ObjectAdapterContext
- * <p>
- * Responsibility: re-creates domain object instances  
- * </p> 
- * @since 2.0.0-M2
- */
-@SuppressWarnings("unused")
-class ObjectAdapterContext_ObjectReCreation {
-    
-    
-    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_ObjectReCreation.class);
-    private final ObjectAdapterContext objectAdapterContext;
-    private final PersistenceSession persistenceSession;
-    private final ServicesInjector servicesInjector;
-    private final SpecificationLoader specificationLoader;
-    
-    
-    ObjectAdapterContext_ObjectReCreation(ObjectAdapterContext objectAdapterContext,
-            PersistenceSession persistenceSession) {
-        this.objectAdapterContext = objectAdapterContext;
-        this.persistenceSession = persistenceSession;
-        this.servicesInjector = persistenceSession.getServicesInjector();
-        this.specificationLoader = servicesInjector.getSpecificationLoader();
-    }
-
-    Object recreateViewModel(final ObjectSpecification spec, final String memento) {
-        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
-        if(facet == null) {
-            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
-        }
-
-        final Object viewModelPojo;
-        if(facet.getRecreationMechanism().isInitializes()) {
-            viewModelPojo = objectAdapterContext.instantiateAndInjectServices(spec);
-            facet.initialize(viewModelPojo, memento);
-        } else {
-            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
-        }
-        return viewModelPojo;
-    }
-    
-}
\ No newline at end of file


[isis] 07/08: ISIS-1976: remove some ObjectAdapter references from PS API

Posted by ah...@apache.org.
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 73d4e28a1934ea43121e1a939778e188bfbe16e5
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 15:22:37 2018 +0200

    ISIS-1976: remove some ObjectAdapter references from PS API
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../applib/services/bookmark/BookmarkService.java  |   2 +-
 .../jaxbadapters/PersistentEntitiesAdapter.java    |   2 +-
 .../jaxbadapters/PersistentEntityAdapter.java      |   2 +-
 .../metamodel/adapter/ObjectAdapterProvider.java   |  30 ++-
 .../system/persistence/PersistenceSession4.java    | 219 ++++++++-------------
 .../system/persistence/PersistenceSession5.java    | 197 ++++++++----------
 .../PersistenceSessionServiceInternalDefault.java  |   2 +-
 .../system/persistence/PersistenceSession.java     |  28 ++-
 .../adaptermanager/ObjectAdapterContext.java       |  60 ++++++
 .../DelegatingInvocationHandlerDefault.java        |   2 +-
 10 files changed, 256 insertions(+), 288 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkService.java b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkService.java
index f45bc17f..fa026ca 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkService.java
@@ -85,7 +85,7 @@ public interface BookmarkService {
         /**
          * Required in order to recreate view models.
          */
-        DONT_RESET
+        DONT_REFRESH
     }
 
 
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntitiesAdapter.java b/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntitiesAdapter.java
index ab962d4..6cf79f3 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntitiesAdapter.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntitiesAdapter.java
@@ -35,7 +35,7 @@ public class PersistentEntitiesAdapter extends XmlAdapter<OidsDto, List<Object>>
         List<Object> domainObjects = _Lists.newArrayList();
         for (final OidDto oidDto : oidsDto.getOid()) {
             final Bookmark bookmark = Bookmark.from(oidDto);
-            Object domainObject = bookmarkService.lookup(bookmark, BookmarkService.FieldResetPolicy.DONT_RESET);
+            Object domainObject = bookmarkService.lookup(bookmark, BookmarkService.FieldResetPolicy.DONT_REFRESH);
             domainObjects.add(domainObject);
         }
         return domainObjects;
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java b/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
index 1a724a1..57efc83 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/jaxbadapters/PersistentEntityAdapter.java
@@ -29,7 +29,7 @@ public class PersistentEntityAdapter extends XmlAdapter<OidDto, Object> {
 
         final Bookmark bookmark = Bookmark.from(oidDto);
 
-        return bookmarkService.lookup(bookmark, BookmarkService.FieldResetPolicy.DONT_RESET);
+        return bookmarkService.lookup(bookmark, BookmarkService.FieldResetPolicy.DONT_REFRESH);
     }
 
     @Override
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 eaf3eb4..773f292 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
@@ -18,10 +18,15 @@
  */
 package org.apache.isis.core.metamodel.adapter;
 
+import static org.apache.isis.commons.internal.base._With.mapIfPresentElse;
+
 import java.util.List;
 import java.util.function.Function;
 
+import javax.annotation.Nullable;
+
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -36,16 +41,18 @@ public interface ObjectAdapterProvider {
     
     // -- INTERFACE
 
-//    /**
-//     * @param pojo
-//     * @return oid for the given domain object 
-//     */
-//    Oid oidFor(Object domainObject);
+    /**
+     * @param pojo
+     * @return oid for the given domain object 
+     */
+    default @Nullable Oid oidFor(@Nullable Object domainObject) {
+        return mapIfPresentElse(adapterFor(domainObject), ObjectAdapter::getOid, null);
+    }
     
     /**
      * @return standalone (value) or root adapter
      */
-    ObjectAdapter adapterFor(Object domainObject);
+    @Nullable ObjectAdapter adapterFor(@Nullable Object domainObject);
 
     /**
      * @return collection adapter.
@@ -85,11 +92,6 @@ public interface ObjectAdapterProvider {
         @Programmatic
         ObjectAdapterProvider getObjectAdapterProvider();
         
-//        @Programmatic
-//        default Oid oidFor(Object domainObject) {
-//            return getObjectAdapterProvider().oidFor(domainObject);
-//        }
-        
         @Programmatic
         default ObjectAdapter adapterFor(Object domainObject) {
             return getObjectAdapterProvider().adapterFor(domainObject);
@@ -126,12 +128,6 @@ public interface ObjectAdapterProvider {
         }
         
     }
-
-
-   
-
-
-    
     
 
 }
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 35230c5..26ff4c0 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
@@ -21,8 +21,6 @@ package org.apache.isis.core.runtime.system.persistence;
 import static java.util.Objects.requireNonNull;
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
 
-import java.lang.reflect.Array;
-import java.lang.reflect.Modifier;
 import java.sql.Timestamp;
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -33,6 +31,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
 import javax.jdo.FetchGroup;
 import javax.jdo.FetchPlan;
 import javax.jdo.PersistenceManager;
@@ -48,7 +47,6 @@ import org.datanucleus.identity.DatastoreIdImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.applib.events.lifecycle.AbstractLifecycleEvent;
 import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
@@ -58,7 +56,6 @@ 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.commons.factory.InstanceUtil;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterByIdProvider;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
@@ -70,9 +67,6 @@ 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.object.callbacks.CallbackFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedCallbackFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacet;
-import org.apache.isis.core.metamodel.facets.object.callbacks.LifecycleEventFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedCallbackFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.PersistedCallbackFacet;
@@ -91,8 +85,6 @@ 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.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.runtime.persistence.FixturesInstalledFlag;
 import org.apache.isis.core.runtime.persistence.NotPersistableException;
 import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
@@ -224,8 +216,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return command;
     }
 
-
-
     // -- close
 
     /**
@@ -502,71 +492,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return !installFixtures;
     }
 
-    // -- loadObject
-
-    /**
-     * 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, {@link AdapterManager#addRecreatedPojoToCache(org.apache.isis.core.metamodel.adapter.oid.Oid, Object) mapped by
-     * the adapter manager}.
-     *
-     * <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 = 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);
-                });
-    }
-
     // -- FETCHING
 
     @Override
@@ -666,47 +591,21 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
 
-    // -- refreshRootInTransaction, refreshRoot, resolve
-
-    /**
-     * Re-initialises 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.
-     */
-    private void refreshRootInTransaction(final ObjectAdapter adapter) {
-        Assert.assertTrue("only resolve object that is persistent", adapter, adapter.representsPersistent());
-        getTransactionManager().executeWithinTransaction(()->{
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("resolveImmediately; oid={}", adapter.getOid().enString());
-                }
-
-                if (!adapter.representsPersistent()) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("; not persistent - ignoring");
-                    }
-                    return;
-                }
-
-                refreshRoot(adapter);
-        });
-    }
-
-    /**
-     * Forces a reload (refresh in JDO terminology) of the domain object wrapped in the {@link ObjectAdapter}.
-     */
+    // -- REFRESH
+    
     @Override
-    public void refreshRoot(final ObjectAdapter adapter) {
-
-        final Object domainObject = adapter.getObject();
-        if (domainObject == null) {
-            // REVIEW: is this possible?
-            throw new PojoRefreshException(adapter.getOid());
+    public void refreshRoot(final Object domainObject) {
+        
+        if(!isRepresentingPersistent(domainObject)) {
+            debugLogNotPersistentIgnoring(domainObject);
+            return; // only resolve object that is representing persistent
         }
 
         try {
             persistenceManager.refresh(domainObject);
         } catch (final RuntimeException e) {
-            throw new PojoRefreshException(adapter.getOid(), e);
+            final Oid oid = oidFor(domainObject);
+            throw new PojoRefreshException(oid, e);
         }
 
         // possibly redundant because also called in the post-load event
@@ -714,15 +613,21 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         // get an eager left-outer-join as the result of a refresh (sounds possible).
         initializeMapAndCheckConcurrency((Persistable) domainObject);
     }
-
+    
     @Override
-    public void resolve(final Object parent) {
-        final ObjectAdapter adapter = adapterFor(parent);
-        refreshRootInTransaction(adapter);
+    public void refreshRootInTransaction(final Object domainObject) {
+        
+        if(!isRepresentingPersistent(domainObject)) {
+            debugLogNotPersistentIgnoring(domainObject);
+            return; // only resolve object that is representing persistent
+        }
+        
+        getTransactionManager().executeWithinTransaction(()->{
+                debugLogRefreshImmediately(domainObject);
+                refreshRoot(domainObject);
+        });
     }
-
-
-
+    
     // -- makePersistent
 
     /**
@@ -810,13 +715,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
         LOG.debug("destroyObject {}", adapter);
         transactionManager.executeWithinTransaction(()->{
-            final DestroyObjectCommand command = newDestroyObjectCommand(adapter);
-            transactionManager.addCommand(command);
+                final DestroyObjectCommand command = newDestroyObjectCommand(adapter);
+                transactionManager.addCommand(command);
         });
     }
 
-
-
     // -- newXxxCommand
     /**
      * Makes an {@link ObjectAdapter} persistent. The specified object should be
@@ -930,7 +833,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return transactionManager.getCurrentTransaction();
     }
 
-
     // -- FrameworkSynchronizer delegate methods
 
     @Override
@@ -1156,36 +1058,60 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return Utils.getVersionIfAny(pojo, authenticationSession);
     }
 
-
-
-
     // -- DomainObjectServices impl
 
     @Override
     public Object lookup(
             final Bookmark bookmark,
             final BookmarkService.FieldResetPolicy fieldResetPolicy) {
-        RootOid oid = RootOid.create(bookmark);
+        final RootOid oid = RootOid.create(bookmark);
+        
         final ObjectAdapter adapter = adapterFor(oid);
         if(adapter == null) {
             return null;
         }
-        if(fieldResetPolicy == BookmarkService.FieldResetPolicy.RESET && !adapter.getSpecification().isViewModel()) {
-            refreshRootInTransaction(adapter);
-        } else {
+        
+        //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) {
 
-    @Override
-    public boolean flush() {
-        return getTransactionManager().flushTransaction();
+        // 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(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isTransient(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isPersistent = p.dnIsPersistent();
             final boolean isDeleted = p.dnIsDeleted();
@@ -1197,8 +1123,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
     @Override
-    public boolean isRepresentingPersistent(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isRepresentingPersistent(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isPersistent = p.dnIsPersistent();
             if (isPersistent) {
@@ -1209,8 +1135,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
     @Override
-    public boolean isDestroyed(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isDestroyed(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isDeleted = p.dnIsDeleted();
             if (isDeleted) {
@@ -1235,7 +1161,22 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return objectAdapterContext.getObjectAdapterByIdProvider();
     }
 
+    // -- HELPER
+    
+    private void debugLogNotPersistentIgnoring(Object domainObject) {
+        if (LOG.isDebugEnabled() && domainObject!=null) {
+            final Oid oid = oidFor(domainObject);
+            LOG.debug("; oid={} not persistent - ignoring", oid.enString());
+        }     
+    }
 
+    private void debugLogRefreshImmediately(Object domainObject) {
+        if (LOG.isDebugEnabled()) {
+            final Oid oid = oidFor(domainObject);
+            LOG.debug("refresh immediately; oid={}", oid.enString());
+        }
+    }
+    
 }
 
 
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 6255c81..38e7d19 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
@@ -31,6 +31,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
 import javax.jdo.FetchGroup;
 import javax.jdo.FetchPlan;
 import javax.jdo.PersistenceManager;
@@ -491,71 +492,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return !installFixtures;
     }
 
-    // -- loadObject
-
-    /**
-     * 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, {@link AdapterManager#addRecreatedPojoToCache(org.apache.isis.core.metamodel.adapter.oid.Oid, Object) mapped by
-     * the adapter manager}.
-     *
-     * <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 = 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);
-                });
-    }
-
     // -- FETCHING
 
     @Override
@@ -655,47 +591,21 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
 
-    // -- refreshRootInTransaction, refreshRoot, resolve
-
-    /**
-     * Re-initialises 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.
-     */
-    private void refreshRootInTransaction(final ObjectAdapter adapter) {
-        Assert.assertTrue("only resolve object that is persistent", adapter, adapter.representsPersistent());
-        getTransactionManager().executeWithinTransaction(()->{
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("resolveImmediately; oid={}", adapter.getOid().enString());
-                }
-
-                if (!adapter.representsPersistent()) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("; not persistent - ignoring");
-                    }
-                    return;
-                }
-
-                refreshRoot(adapter);
-        });
-    }
-
-    /**
-     * Forces a reload (refresh in JDO terminology) of the domain object wrapped in the {@link ObjectAdapter}.
-     */
+    // -- REFRESH
+    
     @Override
-    public void refreshRoot(final ObjectAdapter adapter) {
-
-        final Object domainObject = adapter.getObject();
-        if (domainObject == null) {
-            // REVIEW: is this possible?
-            throw new PojoRefreshException(adapter.getOid());
+    public void refreshRoot(final Object domainObject) {
+        
+        if(!isRepresentingPersistent(domainObject)) {
+            debugLogNotPersistentIgnoring(domainObject);
+            return; // only resolve object that is representing persistent
         }
 
         try {
             persistenceManager.refresh(domainObject);
         } catch (final RuntimeException e) {
-            throw new PojoRefreshException(adapter.getOid(), e);
+            final Oid oid = oidFor(domainObject);
+            throw new PojoRefreshException(oid, e);
         }
 
         // possibly redundant because also called in the post-load event
@@ -703,15 +613,22 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         // get an eager left-outer-join as the result of a refresh (sounds possible).
         initializeMapAndCheckConcurrency((Persistable) domainObject);
     }
-
+    
     @Override
-    public void resolve(final Object parent) {
-        final ObjectAdapter adapter = adapterFor(parent);
-        refreshRootInTransaction(adapter);
+    public void refreshRootInTransaction(final Object domainObject) {
+        
+        if(!isRepresentingPersistent(domainObject)) {
+            debugLogNotPersistentIgnoring(domainObject);
+            return; // only resolve object that is representing persistent
+        }
+        
+        getTransactionManager().executeWithinTransaction(()->{
+                debugLogRefreshImmediately(domainObject);
+                refreshRoot(domainObject);
+        });
     }
 
-
-
+    
     // -- makePersistent
 
     /**
@@ -1148,28 +1065,53 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     public Object lookup(
             final Bookmark bookmark,
             final BookmarkService.FieldResetPolicy fieldResetPolicy) {
-        RootOid oid = RootOid.create(bookmark);
+        final RootOid oid = RootOid.create(bookmark);
+        
         final ObjectAdapter adapter = adapterFor(oid);
         if(adapter == null) {
             return null;
         }
-        if(fieldResetPolicy == BookmarkService.FieldResetPolicy.RESET && !adapter.getSpecification().isViewModel()) {
-            refreshRootInTransaction(adapter);
-        } else {
+        
+        //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) {
 
-    @Override
-    public boolean flush() {
-        return getTransactionManager().flushTransaction();
-    }
+        // 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(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isTransient(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isPersistent = p.dnIsPersistent();
             final boolean isDeleted = p.dnIsDeleted();
@@ -1181,8 +1123,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
     @Override
-    public boolean isRepresentingPersistent(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isRepresentingPersistent(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isPersistent = p.dnIsPersistent();
             if (isPersistent) {
@@ -1193,8 +1135,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
     @Override
-    public boolean isDestroyed(Object pojo) {
-        if (pojo instanceof Persistable) {
+    public boolean isDestroyed(@Nullable Object pojo) {
+        if (pojo!=null && pojo instanceof Persistable) {
             final Persistable p = (Persistable) pojo;
             final boolean isDeleted = p.dnIsDeleted();
             if (isDeleted) {
@@ -1219,7 +1161,22 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return objectAdapterContext.getObjectAdapterByIdProvider();
     }
 
+    // -- HELPER
+    
+    private void debugLogNotPersistentIgnoring(Object domainObject) {
+        if (LOG.isDebugEnabled() && domainObject!=null) {
+            final Oid oid = oidFor(domainObject);
+            LOG.debug("; oid={} not persistent - ignoring", oid.enString());
+        }     
+    }
 
+    private void debugLogRefreshImmediately(Object domainObject) {
+        if (LOG.isDebugEnabled()) {
+            final Oid oid = oidFor(domainObject);
+            LOG.debug("refresh immediately; oid={}", oid.enString());
+        }
+    }
+    
 }
 
 
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 1d9f192..4ba74ad 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
@@ -111,7 +111,7 @@ public class PersistenceSessionServiceInternalDefault implements PersistenceSess
 
     @Override
     public void resolve(final Object parent) {
-        getPersistenceSession().resolve(parent);
+        getPersistenceSession().refreshRootInTransaction(parent);
     }
 
     /**
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 af0a2e8..3c63285 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
@@ -29,6 +29,7 @@ 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;
@@ -50,15 +51,29 @@ extends
     // -- STABLE API (DRAFT)
     // -------------------------------------------------------------------------------------------------
     
-    void open();
-    void close();
-    boolean flush();
-    void resolve(Object parent);
-    
     IsisConfiguration getConfiguration();
     IsisTransactionManager getTransactionManager();
     ServicesInjector getServicesInjector();
     
+    void open();
+    void close();
+    
+    default boolean flush() {
+        return getTransactionManager().flushTransaction();
+    }
+    
+    /**
+     * Forces a reload (refresh in JDO terminology) of the domain object
+     */
+    void refreshRoot(Object domainObject);
+    
+    /**
+     * Re-initialises 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.
+     */
+    void refreshRootInTransaction(Object domainObject);
+    
     /**
      * @param pojo a persistable object
      * @return String representing an object's id.
@@ -159,13 +174,12 @@ extends
     
     void makePersistentInTransaction(ObjectAdapter adapter);
     
-    void refreshRoot(ObjectAdapter adapter);
-    
     // -- OTHERS
     
     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 d4ac548..4de6fb5 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
@@ -506,7 +506,67 @@ 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);
+                });
+    }
 
 
 
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 ffaf8ed..3056749 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
@@ -81,7 +81,7 @@ public class DelegatingInvocationHandlerDefault<T> implements DelegatingInvocati
 
     protected void resolveIfRequired(final Object domainObject) {
         if (resolveObjectChangedEnabled) {
-            getPersistenceSession().resolve(domainObject);
+            getPersistenceSession().refreshRootInTransaction(domainObject);
         }
     }
 


[isis] 08/08: ISIS-1976: further remove OA references from PS API

Posted by ah...@apache.org.
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 <ah...@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());


[isis] 03/08: ISIS-1976: refactor OA-by-Oid supply responsibility into new interface

Posted by ah...@apache.org.
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 2a7dd9dad4d573dd874b09188f60be9191834f8a
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 10:57:54 2018 +0200

    ISIS-1976: refactor OA-by-Oid supply responsibility into new interface
    
    introduces ObjectAdapterByIdProvider
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../adapter/ObjectAdapterByIdProvider.java         |  86 +++++++++
 .../system/persistence/PersistenceSession4.java    |  79 +++-----
 .../persistence/PersistenceSession4_Decouple.java  | 213 ---------------------
 .../system/persistence/PersistenceSession5.java    |  67 ++-----
 .../system/persistence/PersistenceSession.java     |  36 ++--
 .../adaptermanager/ObjectAdapterContext.java       |  12 ++
 ...tAdapterContext_ObjectAdapterByIdProvider.java} | 129 +++++++++----
 .../wicket/model/models/EntityCollectionModel.java |  12 +-
 8 files changed, 254 insertions(+), 380 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterByIdProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterByIdProvider.java
new file mode 100644
index 0000000..d8928bf
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterByIdProvider.java
@@ -0,0 +1,86 @@
+/*
+ *  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.metamodel.adapter;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.core.metamodel.adapter.concurrency.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+
+/**
+ * 
+ * @since 2.0.0-M2
+ *
+ */
+public interface ObjectAdapterByIdProvider {
+    
+    // -- INTERFACE
+
+    ObjectAdapter adapterFor(RootOid rootOid, ConcurrencyChecking concurrencyChecking);
+    Map<RootOid, ObjectAdapter> adaptersFor(Stream<RootOid> rootOids, ConcurrencyChecking concurrencyChecking);
+    
+    /**
+     * As per {@link #adapterFor(RootOid, ConcurrencyChecking)}, with
+     * {@link ConcurrencyChecking#NO_CHECK no checking}.
+     *
+     * <p>
+     * This method  will <i>always</i> return an object, possibly indicating it is persistent; so make sure that you
+     * know that the oid does indeed represent an object you know exists.
+     * </p>
+     */
+    default ObjectAdapter adapterFor(final RootOid rootOid) {
+        return adapterFor(rootOid, ConcurrencyChecking.NO_CHECK);
+    }
+    
+    default Map<RootOid, ObjectAdapter> adaptersFor(Stream<RootOid> rootOids) {
+        return adaptersFor(rootOids, ConcurrencyChecking.NO_CHECK);
+    }
+    
+    
+    // -- FOR THOSE THAT IMPLEMENT THROUGH DELEGATION
+    
+    public static interface Delegating extends ObjectAdapterByIdProvider {
+        
+        @Programmatic
+        ObjectAdapterByIdProvider getObjectAdapterByIdProvider();
+        
+        @Programmatic
+        default ObjectAdapter adapterFor(RootOid rootOid, ConcurrencyChecking concurrencyChecking) {
+            return getObjectAdapterByIdProvider().adapterFor(rootOid, concurrencyChecking);
+        }
+        
+        
+        @Programmatic
+        default Map<RootOid, ObjectAdapter> adaptersFor(Stream<RootOid> rootOids, ConcurrencyChecking concurrencyChecking) {
+            return getObjectAdapterByIdProvider().adaptersFor(rootOids, concurrencyChecking);
+        }
+
+        
+    }
+
+
+   
+
+
+    
+    
+
+}
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 7ba1caa..390853a 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
@@ -18,12 +18,14 @@
  */
 package org.apache.isis.core.runtime.system.persistence;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
 import java.sql.Timestamp;
 import java.text.MessageFormat;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -38,7 +40,6 @@ import javax.jdo.PersistenceManagerFactory;
 import javax.jdo.identity.SingleFieldIdentity;
 import javax.jdo.listener.InstanceLifecycleListener;
 
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import org.datanucleus.enhancement.Persistable;
@@ -54,12 +55,12 @@ 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.collections._Lists;
 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.commons.factory.InstanceUtil;
 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.concurrency.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
@@ -127,7 +128,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession4.class);
     private ObjectAdapterContext objectAdapterContext;
-    private PersistenceSession4_Decouple mixin;
 
     /**
      * Initialize the object store so that calls to this object store access
@@ -170,7 +170,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 new PersistenceQueryFindUsingApplibQueryProcessor(this));
 
         objectAdapterContext = ObjectAdapterContext.openContext(servicesInjector, authenticationSession, specificationLoader, this);
-        mixin = new PersistenceSession4_Decouple(this, objectAdapterContext);
 
         // tell the proxy of all request-scoped services to instantiate the underlying
         // services, store onto the thread-local and inject into them...
@@ -477,6 +476,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return initializePropertiesAndDoCallback(adapter);
     }
 
+    //FIXME[ISIS-1976] remove
     private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
         final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
         if(facet == null) {
@@ -695,19 +695,16 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                     public ObjectAdapter execute() {
                         LOG.debug("getObject; oid={}", oid);
 
-                        final Object pojo = loadPersistentPojo(oid);
+                        final Object pojo = fetchPersistentPojo(oid);
                         return objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
                     }
                 });
     }
 
+    // -- FETCHING
 
-
-
-    // -- loadPersistentPojo
-
-    //TODO[ISIS-1976] used by mixin
-    Object loadPersistentPojo(final RootOid rootOid) {
+    @Override
+    public Object fetchPersistentPojo(final RootOid rootOid) {
 
         Object result;
         try {
@@ -739,14 +736,14 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return result;
     }
 
-    //TODO[ISIS-1976] used by mixin
-    Map<RootOid,Object> loadPersistentPojos(final List<RootOid> rootOids) {
+    @Override
+    public Map<RootOid,Object> fetchPersistentPojos(final List<RootOid> rootOids) {
 
         if(rootOids.isEmpty()) {
-            return zip(rootOids, Collections.emptyList());
+            return Collections.emptyMap();
         }
 
-        final List<Object> dnOids = _Lists.newArrayList();
+        final List<Object> dnOids = new ArrayList<>(rootOids.size());
         for (final RootOid rootOid : rootOids) {
             final Object id = JdoObjectIdSerializer.toJdoObjectId(rootOid);
             if(id instanceof SingleFieldIdentity) {
@@ -762,7 +759,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
         FetchPlan fetchPlan = persistenceManager.getFetchPlan();
         fetchPlan.addGroup(FetchGroup.DEFAULT);
-        final List<Object> persistentPojos = Lists.newArrayList();
+        final List<Object> persistentPojos = new ArrayList<>(rootOids.size());
         try {
             final Collection<Object> pojos = uncheckedCast(persistenceManager.getObjectsById(dnOids, true));
             for (final Object pojo : pojos) {
@@ -1077,40 +1074,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
     }
 
-    @Override
-    public Map<RootOid, ObjectAdapter> adaptersFor(
-            final List<RootOid> rootOids,
-            final ConcurrencyChecking concurrencyChecking) {
-
-        return mixin.adaptersFor(rootOids, concurrencyChecking);
-        }
-
-    @Override
-    public ObjectAdapter adapterFor(
-            final RootOid rootOid,
-            final ConcurrencyChecking concurrencyChecking) {
-
-        return mixin.adapterFor(rootOid, concurrencyChecking);
-            }
-
-    //TODO[ISIS-1976] used by mixin
-    Object recreatePojoTransientOrViewModel(final RootOid rootOid) {
-        final ObjectSpecification spec =
-                specificationLoader.lookupBySpecId(rootOid.getObjectSpecId());
-        final Object pojo;
-
-        if(rootOid.isViewModel()) {
-
-            final String memento = rootOid.getIdentifier();
-            pojo = recreateViewModel(spec, memento);
-
-        } else {
-            pojo = instantiateAndInjectServices(spec);
-
-        }
-        return pojo;
-    }
-
     // -- TransactionManager delegate methods
     protected IsisTransaction getCurrentTransaction() {
         return transactionManager.getCurrentTransaction();
@@ -1202,7 +1165,15 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     @Override
     public String identifierFor(final Object pojo) {
-        return JdoObjectIdSerializer.toOidIdentifier(getPersistenceManager().getObjectId(pojo));
+        final Object jdoOid = getPersistenceManager().getObjectId(pojo);
+        if(jdoOid==null) {
+            return UUID.randomUUID().toString(); //FIXME[ISIS-1976] should be guarded against somewhere else
+        }
+        
+        requireNonNull(jdoOid, 
+                ()->String.format("Pojo of type '%s' is not recognized by JDO.", 
+                        pojo.getClass().getName()));
+        return JdoObjectIdSerializer.toOidIdentifier(jdoOid);
     }
 
 
@@ -1408,6 +1379,12 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return objectAdapterContext.getObjectAdapterProvider();
     }
     
+    @Override
+    public ObjectAdapterByIdProvider getObjectAdapterByIdProvider() {
+        return objectAdapterContext.getObjectAdapterByIdProvider();
+    }
+
+
 }
 
 
diff --git a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4_Decouple.java b/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4_Decouple.java
deleted file mode 100644
index de33ef0..0000000
--- a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4_Decouple.java
+++ /dev/null
@@ -1,213 +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
- *
- *        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;
-
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-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.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.concurrency.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.adapter.oid.Oid;
-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.runtime.persistence.ObjectNotFoundException;
-import org.apache.isis.core.runtime.persistence.PojoRecreationException;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext;
-
-class PersistenceSession4_Decouple  {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession4_Decouple.class);
-    private final PersistenceSession4 holder;
-    private final ObjectAdapterContext objectAdapterContext;
-    private final AuthenticationSession authenticationSession;
-    private final boolean concurrencyCheckingGloballyEnabled;
-
-    protected PersistenceSession4_Decouple(PersistenceSession4 holder, ObjectAdapterContext objectAdapterContext) {
-        this.holder = holder;
-        this.objectAdapterContext = objectAdapterContext;
-        this.authenticationSession = holder.getAuthenticationSession();
-        this.concurrencyCheckingGloballyEnabled = !ConcurrencyChecking.isGloballyDisabled(holder.getConfiguration());
-    }
-
-    /**
-     * Either returns an existing {@link ObjectAdapter adapter} (as per
-     * {@link #lookupAdapterFor(Oid)}), otherwise re-creates an adapter with the
-     * specified (persistent) {@link Oid}.
-     *
-     * <p>
-     * Typically called when the {@link Oid} is already known, that is, when
-     * resolving an already-persisted object. Is also available for
-     * <tt>Memento</tt> support however, so {@link Oid} could also represent a
-     * {@link Oid#isTransient() transient} object.
-     *
-     * <p>
-     * The pojo itself is recreated by delegating to a {@link AdapterManager}.
-     *
-     * <p>
-     * The {@link ConcurrencyChecking} parameter determines whether concurrency checking is performed.
-     * If it is requested, then a check is made to ensure that the {@link Oid#getVersion() version}
-     * of the {@link RootOid oid} of the recreated adapter is the same as that of the provided {@link RootOid oid}.
-     * If the version differs, then a {@link ConcurrencyException} is thrown.
-     *
-     * <p>
-     * ALSO, even if a {@link ConcurrencyException}, then the provided {@link RootOid oid}'s {@link Version version}
-     * will be {@link RootOid#setVersion(Version) set} to the current
-     * value.  This allows the client to retry if they wish.
-     *
-     * @throws {@link org.apache.isis.core.runtime.persistence.ObjectNotFoundException} if the object does not exist.
-     */
-    public ObjectAdapter adapterFor(
-            final RootOid rootOid,
-            final ConcurrencyChecking concurrencyChecking) {
-
-        // attempt to locate adapter for the Oid
-        ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(rootOid);
-        if (adapter == null) {
-            // else recreate
-            try {
-                final Object pojo;
-                if(rootOid.isTransient() || rootOid.isViewModel()) {
-                    pojo = holder.recreatePojoTransientOrViewModel(rootOid);
-                } else {
-                    pojo = holder.loadPersistentPojo(rootOid);
-                }
-                adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
-            } catch(ObjectNotFoundException ex) {
-                throw ex; // just rethrow
-            } catch(RuntimeException ex) {
-                throw new PojoRecreationException(rootOid, ex);
-            }
-        }
-
-        // sync versions of original, with concurrency checking if required
-        syncVersion(concurrencyChecking, adapter, rootOid);
-
-        return adapter;
-
-    }
-    
-    protected Map<RootOid,ObjectAdapter> adaptersFor(
-            final List<RootOid> rootOids,
-            final ConcurrencyChecking concurrencyChecking) {
-
-        final Map<RootOid, ObjectAdapter> adapterByOid = _Maps.newLinkedHashMap();
-
-        List<RootOid> notYetLoadedOids = _Lists.newArrayList();
-        for (RootOid rootOid : rootOids) {
-            // attempt to locate adapter for the Oid
-            ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(rootOid);
-            // handle view models or transient
-            if (adapter == null) {
-                if (rootOid.isTransient() || rootOid.isViewModel()) {
-                    final Object pojo = holder.recreatePojoTransientOrViewModel(rootOid);
-                    adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
-                    syncVersion(concurrencyChecking, adapter, rootOid);
-                }
-            }
-            if (adapter != null) {
-                adapterByOid.put(rootOid, adapter);
-            } else {
-                // persistent oid, to load in bulk
-                notYetLoadedOids.add(rootOid);
-            }
-        }
-
-        // recreate, in bulk, all those not yet loaded
-        final Map<RootOid, Object> pojoByOid = holder.loadPersistentPojos(notYetLoadedOids);
-        for (Map.Entry<RootOid, Object> entry : pojoByOid.entrySet()) {
-            final RootOid rootOid = entry.getKey();
-            final Object pojo = entry.getValue();
-            if(pojo != null) {
-                ObjectAdapter adapter;
-                try {
-                    adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
-                    adapterByOid.put(rootOid, adapter);
-                } catch(ObjectNotFoundException ex) {
-                    throw ex; // just rethrow
-                } catch(RuntimeException ex) {
-                    throw new PojoRecreationException(rootOid, ex);
-                }
-                syncVersion(concurrencyChecking, adapter, rootOid);
-            } else {
-                // null indicates it couldn't be loaded
-                // do nothing here...
-            }
-        }
-
-        return adapterByOid;
-    }
-
-    private void syncVersion(
-            final ConcurrencyChecking concurrencyChecking,
-            final ObjectAdapter adapter, final RootOid rootOid) {
-        // sync versions of original, with concurrency checking if required
-        Oid adapterOid = adapter.getOid();
-        if(adapterOid instanceof RootOid) {
-            final RootOid recreatedOid = (RootOid) adapterOid;
-            final RootOid originalOid = rootOid;
-
-            try {
-                if(concurrencyChecking.isChecking()) {
-
-                    // check for exception, but don't throw if suppressed through thread-local
-                    final Version otherVersion = originalOid.getVersion();
-                    final Version thisVersion = recreatedOid.getVersion();
-                    if( thisVersion != null &&
-                            otherVersion != null &&
-                            thisVersion.different(otherVersion)) {
-
-                        if(concurrencyCheckingGloballyEnabled && ConcurrencyChecking.isCurrentlyEnabled()) {
-                            LOG.info("concurrency conflict detected on {} ({})", recreatedOid, otherVersion);
-                            final String currentUser = authenticationSession.getUserName();
-                            throw new ConcurrencyException(currentUser, recreatedOid, thisVersion, otherVersion);
-                        } else {
-                            LOG.info("concurrency conflict detected but suppressed, on {} ({})", recreatedOid, otherVersion);
-                        }
-                    }
-                }
-            } finally {
-                final Version originalVersion = originalOid.getVersion();
-                final Version recreatedVersion = recreatedOid.getVersion();
-                if(recreatedVersion != null && (
-                        originalVersion == null ||
-                        recreatedVersion.different(originalVersion))
-                        ) {
-                    if(LOG.isDebugEnabled()) {
-                        LOG.debug("updating version in oid, on {} ({}) to ({})", originalOid, originalVersion, recreatedVersion);
-                    }
-                    originalOid.setVersion(recreatedVersion);
-                }
-            }
-        }
-    }
-
-
-
-
-}
-
-
-
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 2a9ec77..0fae449 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
@@ -25,6 +25,7 @@ import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
 import java.sql.Timestamp;
 import java.text.MessageFormat;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -34,18 +35,14 @@ import java.util.UUID;
 
 import javax.jdo.FetchGroup;
 import javax.jdo.FetchPlan;
-import javax.jdo.JDOHelper;
 import javax.jdo.PersistenceManager;
 import javax.jdo.PersistenceManagerFactory;
 import javax.jdo.identity.SingleFieldIdentity;
 import javax.jdo.listener.InstanceLifecycleListener;
 
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import org.datanucleus.enhancement.Persistable;
-import org.datanucleus.enhancer.methods.IsDeleted;
-import org.datanucleus.enhancer.methods.IsPersistent;
 import org.datanucleus.exceptions.NucleusObjectNotFoundException;
 import org.datanucleus.identity.DatastoreIdImpl;
 import org.slf4j.Logger;
@@ -58,12 +55,12 @@ 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.collections._Lists;
 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.commons.factory.InstanceUtil;
 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.concurrency.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
@@ -131,7 +128,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession5.class);
     private ObjectAdapterContext objectAdapterContext;
-    private PersistenceSession5_Decouple mixin;
 
     /**
      * Initialize the object store so that calls to this object store access
@@ -174,7 +170,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 new PersistenceQueryFindUsingApplibQueryProcessor(this));
 
         objectAdapterContext = ObjectAdapterContext.openContext(servicesInjector, authenticationSession, specificationLoader, this);
-        mixin = new PersistenceSession5_Decouple(this, objectAdapterContext);
 
         // tell the proxy of all request-scoped services to instantiate the underlying
         // services, store onto the thread-local and inject into them...
@@ -479,6 +474,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return initializePropertiesAndDoCallback(adapter);
     }
 
+    //FIXME[ISIS-1976] remove
     private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
         final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
         if(facet == null) {
@@ -697,16 +693,16 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                     public ObjectAdapter execute() {
                         LOG.debug("getObject; oid={}", oid);
 
-                        final Object pojo = loadPersistentPojo(oid);
+                        final Object pojo = fetchPersistentPojo(oid);
                         return objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
                     }
                 });
     }
 
-    // -- loadPersistentPojo
+    // -- FETCHING
 
-    //TODO[ISIS-1976] used by mixin
-    Object loadPersistentPojo(final RootOid rootOid) {
+    @Override
+    public Object fetchPersistentPojo(final RootOid rootOid) {
 
         Object result;
         try {
@@ -738,14 +734,14 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return result;
     }
 
-    //TODO[ISIS-1976] used by mixin
-    Map<RootOid,Object> loadPersistentPojos(final List<RootOid> rootOids) {
+    @Override
+    public Map<RootOid,Object> fetchPersistentPojos(final List<RootOid> rootOids) {
 
         if(rootOids.isEmpty()) {
-            return zip(rootOids, Collections.emptyList());
+            return Collections.emptyMap();
         }
 
-        final List<Object> dnOids = _Lists.newArrayList();
+        final List<Object> dnOids = new ArrayList<>(rootOids.size());
         for (final RootOid rootOid : rootOids) {
             final Object id = JdoObjectIdSerializer.toJdoObjectId(rootOid);
             if(id instanceof SingleFieldIdentity) {
@@ -761,7 +757,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
         FetchPlan fetchPlan = persistenceManager.getFetchPlan();
         fetchPlan.addGroup(FetchGroup.DEFAULT);
-        final List<Object> persistentPojos = Lists.newArrayList();
+        final List<Object> persistentPojos = new ArrayList<>(rootOids.size());
         try {
             final Collection<Object> pojos = uncheckedCast(persistenceManager.getObjectsById(dnOids, true));
             for (final Object pojo : pojos) {
@@ -1074,40 +1070,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
     }
 
-    @Override
-    public Map<RootOid, ObjectAdapter> adaptersFor(
-            final List<RootOid> rootOids, 
-            final ConcurrencyChecking concurrencyChecking) {
-
-        return mixin.adaptersFor(rootOids, concurrencyChecking);
-    }
-
-    @Override
-    public ObjectAdapter adapterFor(
-            final RootOid rootOid,
-            final ConcurrencyChecking concurrencyChecking) {
-
-        return mixin.adapterFor(rootOid, concurrencyChecking);
-    }
-
-    //TODO[ISIS-1976] used by mixin
-    Object recreatePojoTransientOrViewModel(final RootOid rootOid) {
-        final ObjectSpecification spec =
-                specificationLoader.lookupBySpecId(rootOid.getObjectSpecId());
-        final Object pojo;
-
-        if(rootOid.isViewModel()) {
-
-            final String memento = rootOid.getIdentifier();
-            pojo = recreateViewModel(spec, memento);
-
-        } else {
-            pojo = instantiateAndInjectServices(spec);
-
-        }
-        return pojo;
-    }
-
     // -- TransactionManager delegate methods
     protected IsisTransaction getCurrentTransaction() {
         return transactionManager.getCurrentTransaction();
@@ -1409,6 +1371,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     public ObjectAdapterProvider getObjectAdapterProvider() {
         return objectAdapterContext.getObjectAdapterProvider();
     }
+    
+    @Override
+    public ObjectAdapterByIdProvider getObjectAdapterByIdProvider() {
+        return objectAdapterContext.getObjectAdapterByIdProvider();
+    }
 
 
 }
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 eec2996..2354136 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
@@ -27,8 +27,8 @@ 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.concurrency.ConcurrencyChecking;
 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;
@@ -39,7 +39,12 @@ import org.apache.isis.core.runtime.runner.opts.OptionHandlerFixtureAbstract;
 import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 
-public interface PersistenceSession extends ObjectAdapterProvider.Delegating, TransactionalResource, SessionScopedComponent {
+public interface PersistenceSession 
+extends 
+    ObjectAdapterProvider.Delegating,
+    ObjectAdapterByIdProvider.Delegating,
+    TransactionalResource, 
+    SessionScopedComponent {
 
     // -- CONSTANTS
 
@@ -55,27 +60,8 @@ public interface PersistenceSession extends ObjectAdapterProvider.Delegating, Tr
 
     MementoRecreateObjectSupport mementoSupport();
 
-    ObjectAdapter adapterFor(RootOid rootOid, ConcurrencyChecking concurrencyChecking);
-    Map<RootOid, ObjectAdapter> adaptersFor(List<RootOid> rootOids, ConcurrencyChecking concurrencyChecking);
     ObjectAdapter adapterForAny(RootOid rootOid);
     <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query);
-    
-    /**
-     * As per {@link #adapterFor(RootOid, ConcurrencyChecking)}, with
-     * {@link ConcurrencyChecking#NO_CHECK no checking}.
-     *
-     * <p>
-     * This method  will <i>always</i> return an object, possibly indicating it is persistent; so make sure that you
-     * know that the oid does indeed represent an object you know exists.
-     * </p>
-     */
-    default ObjectAdapter adapterFor(final RootOid rootOid) {
-        return adapterFor(rootOid, ConcurrencyChecking.NO_CHECK);
-    }
-    
-    default Map<RootOid, ObjectAdapter> adaptersFor(List<RootOid> rootOids) {
-        return adaptersFor(rootOids, ConcurrencyChecking.NO_CHECK);
-    }
 
     // --
 
@@ -111,6 +97,10 @@ public interface PersistenceSession extends ObjectAdapterProvider.Delegating, Tr
     boolean isRepresentingPersistent(Object pojo);
     /**@since 2.0.0-M2*/
     boolean isDestroyed(Object pojo);
+    /**@since 2.0.0-M2*/
+    Object fetchPersistentPojo(RootOid rootOid);
+    /**@since 2.0.0-M2*/
+    Map<RootOid, Object> fetchPersistentPojos(List<RootOid> rootOids);
 
     /**
      * Convenient equivalent to {@code getPersistenceManager()}.
@@ -167,8 +157,6 @@ public interface PersistenceSession extends ObjectAdapterProvider.Delegating, Tr
 
     void resolve(Object parent);
 
-
-
-
+    
 
 }
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 6f5df49..f4a21fa 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
@@ -29,7 +29,9 @@ 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.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.concurrency.ConcurrencyChecking;
 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;
@@ -131,6 +133,7 @@ public class ObjectAdapterContext {
     private final ObjectAdapterContext_MementoSupport mementoSupportMixin;
     private final ObjectAdapterContext_ServiceLookup serviceLookupMixin;
     private final ObjectAdapterContext_NewIdentifier newIdentifierMixin;
+    private final ObjectAdapterContext_ObjectAdapterByIdProvider byIdMixin;
     
     private ObjectAdapterContext(
             ServicesInjector servicesInjector, 
@@ -144,6 +147,7 @@ public class ObjectAdapterContext {
         this.mementoSupportMixin = new ObjectAdapterContext_MementoSupport(this, persistenceSession);
         this.serviceLookupMixin = new ObjectAdapterContext_ServiceLookup(this, servicesInjector);
         this.newIdentifierMixin = new ObjectAdapterContext_NewIdentifier(this, persistenceSession);
+        this.byIdMixin = new ObjectAdapterContext_ObjectAdapterByIdProvider(this, persistenceSession, authenticationSession);
         
         this.persistenceSession = persistenceSession;
         this.servicesInjector = servicesInjector;
@@ -233,6 +237,12 @@ public class ObjectAdapterContext {
         return serviceLookupMixin.lookupServiceAdapterFor(rootOid);
     }
     
+    // -- BY-ID SUPPORT
+    
+    public ObjectAdapterByIdProvider getObjectAdapterByIdProvider() {
+        return byIdMixin;
+    }
+    
     // -- FACTORIES
     
     // package private
@@ -465,6 +475,8 @@ public class ObjectAdapterContext {
         return newAdapter;
     }
 
+
+
    
 
 
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java
similarity index 71%
rename from core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java
rename to core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java
index e40f9c3..c4a8af3 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_Decouple.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterByIdProvider.java
@@ -16,43 +16,64 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.core.runtime.system.persistence;
+package org.apache.isis.core.runtime.system.persistence.adaptermanager;
 
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 
 import org.slf4j.Logger;
 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;
 import org.apache.isis.core.metamodel.adapter.concurrency.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 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.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
 import org.apache.isis.core.runtime.persistence.PojoRecreationException;
-import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 
-class PersistenceSession5_Decouple  {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession5_Decouple.class);
-    private final PersistenceSession5 holder;
+/**
+ * package private mixin for ObjectAdapterContext
+ * <p>
+ * Responsibility: creates RootOids 
+ * </p> 
+ * @since 2.0.0-M2
+ */
+class ObjectAdapterContext_ObjectAdapterByIdProvider implements ObjectAdapterByIdProvider {
+    
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_ObjectAdapterByIdProvider.class);
     private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector;
+    private final SpecificationLoader specificationLoader;
     private final AuthenticationSession authenticationSession;
     private final boolean concurrencyCheckingGloballyEnabled;
-
-    protected PersistenceSession5_Decouple(PersistenceSession5 holder, ObjectAdapterContext objectAdapterContext) {
-        this.holder = holder;
+    
+    
+    ObjectAdapterContext_ObjectAdapterByIdProvider(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession, AuthenticationSession authenticationSession) {
         this.objectAdapterContext = objectAdapterContext;
-        this.authenticationSession = holder.getAuthenticationSession();
-        this.concurrencyCheckingGloballyEnabled = !ConcurrencyChecking.isGloballyDisabled(holder.getConfiguration());
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+        this.specificationLoader = servicesInjector.getSpecificationLoader();
+        this.authenticationSession = authenticationSession;
+        
+        this.concurrencyCheckingGloballyEnabled = 
+                !ConcurrencyChecking.isGloballyDisabled(persistenceSession.getConfiguration());
     }
-
+    
     /**
      * Either returns an existing {@link ObjectAdapter adapter} (as per
      * {@link #lookupAdapterFor(Oid)}), otherwise re-creates an adapter with the
@@ -65,7 +86,7 @@ class PersistenceSession5_Decouple  {
      * {@link Oid#isTransient() transient} object.
      *
      * <p>
-     * The pojo itself is recreated by delegating to a {@link AdapterManager}.
+     * The pojo itself is recreated by delegating to a FIXME:AdapterManager
      *
      * <p>
      * The {@link ConcurrencyChecking} parameter determines whether concurrency checking is performed.
@@ -80,11 +101,12 @@ class PersistenceSession5_Decouple  {
      *
      * @throws {@link org.apache.isis.core.runtime.persistence.ObjectNotFoundException} if the object does not exist.
      */
+    @Override
     public ObjectAdapter adapterFor(
             final RootOid rootOid,
             final ConcurrencyChecking concurrencyChecking) {
-        
-        /* FIXME[ISIS-1976] guard against service lookup
+                
+        /* FIXME[ISIS-1976] 
          * https://github.com/apache/isis/pull/121#discussion_r215889748
          * 
          * Eventually I'm hoping that this code will simplify and then become pluggable.
@@ -101,10 +123,11 @@ class PersistenceSession5_Decouple  {
          * into some other datastore. So really my "PersistenceProvider" is a
          * generalization of that concept).
          */
-
+        
+        //FIXME[ISIS-1976] remove guard
         final ObjectAdapter serviceAdapter = objectAdapterContext.lookupServiceAdapterFor(rootOid);
         if (serviceAdapter != null) {
-            _Exceptions.unexpectedCodeReach();
+            //_Exceptions.unexpectedCodeReach();
             return serviceAdapter;
         }
         
@@ -115,9 +138,9 @@ class PersistenceSession5_Decouple  {
             try {
                 final Object pojo;
                 if(rootOid.isTransient() || rootOid.isViewModel()) {
-                    pojo = holder.recreatePojoTransientOrViewModel(rootOid);
+                    pojo = recreatePojoTransientOrViewModel(rootOid);
                 } else {
-                    pojo = holder.loadPersistentPojo(rootOid);
+                    pojo = persistenceSession.fetchPersistentPojo(rootOid);
                 }
                 adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
             } catch(ObjectNotFoundException ex) {
@@ -131,23 +154,25 @@ class PersistenceSession5_Decouple  {
         syncVersion(concurrencyChecking, adapter, rootOid);
 
         return adapter;
-
+        
     }
     
-    protected Map<RootOid,ObjectAdapter> adaptersFor(
-            final List<RootOid> rootOids,
+    @Override
+    public Map<RootOid,ObjectAdapter> adaptersFor(
+            final Stream<RootOid> rootOids,
             final ConcurrencyChecking concurrencyChecking) {
 
         final Map<RootOid, ObjectAdapter> adapterByOid = _Maps.newLinkedHashMap();
 
         List<RootOid> notYetLoadedOids = _Lists.newArrayList();
-        for (RootOid rootOid : rootOids) {
-            // attempt to locate adapter for the Oid
+        
+        rootOids.forEach(rootOid->{
+         // attempt to locate adapter for the Oid
             ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(rootOid);
             // handle view models or transient
             if (adapter == null) {
                 if (rootOid.isTransient() || rootOid.isViewModel()) {
-                    final Object pojo = holder.recreatePojoTransientOrViewModel(rootOid);
+                    final Object pojo = recreatePojoTransientOrViewModel(rootOid);
                     adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
                     syncVersion(concurrencyChecking, adapter, rootOid);
                 }
@@ -158,10 +183,10 @@ class PersistenceSession5_Decouple  {
                 // persistent oid, to load in bulk
                 notYetLoadedOids.add(rootOid);
             }
-        }
-
+        });
+        
         // recreate, in bulk, all those not yet loaded
-        final Map<RootOid, Object> pojoByOid = holder.loadPersistentPojos(notYetLoadedOids);
+        final Map<RootOid, Object> pojoByOid = persistenceSession.fetchPersistentPojos(notYetLoadedOids);
         for (Map.Entry<RootOid, Object> entry : pojoByOid.entrySet()) {
             final RootOid rootOid = entry.getKey();
             final Object pojo = entry.getValue();
@@ -184,7 +209,42 @@ class PersistenceSession5_Decouple  {
 
         return adapterByOid;
     }
+    
+    // -- HELPER
+    
+    private Object recreatePojoTransientOrViewModel(final RootOid rootOid) {
+        final ObjectSpecification spec =
+                specificationLoader.lookupBySpecId(rootOid.getObjectSpecId());
+        final Object pojo;
 
+        if(rootOid.isViewModel()) {
+
+            final String memento = rootOid.getIdentifier();
+            pojo = recreateViewModel(spec, memento);
+
+        } else {
+            pojo = persistenceSession.instantiateAndInjectServices(spec);
+
+        }
+        return pojo;
+    }
+    
+    private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
+        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
+        if(facet == null) {
+            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
+        }
+
+        final Object viewModelPojo;
+        if(facet.getRecreationMechanism().isInitializes()) {
+            viewModelPojo = persistenceSession.instantiateAndInjectServices(spec);
+            facet.initialize(viewModelPojo, memento);
+        } else {
+            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
+        }
+        return viewModelPojo;
+    }
+    
     private void syncVersion(
             final ConcurrencyChecking concurrencyChecking,
             final ObjectAdapter adapter, final RootOid rootOid) {
@@ -228,11 +288,6 @@ class PersistenceSession5_Decouple  {
             }
         }
     }
-
-
-
-
-}
-
-
-
+    
+    
+}
\ No newline at end of file
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
index 5970611..9f86432 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.viewer.wicket.model.models;
 
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
@@ -97,18 +99,18 @@ UiHintContainer {
 
                 final PersistenceSession persistenceSession = model.getPersistenceSession();
 
-                final List<RootOid> rootOids =
-                        _Lists.transform(model.mementoList, ObjectAdapterMemento.Functions.toOid());
-
+                final Stream<RootOid> rootOids = stream(model.mementoList)
+                        .map(ObjectAdapterMemento.Functions.toOid());
+                
                 final Map<RootOid, ObjectAdapter> adaptersByOid = persistenceSession.adaptersFor(rootOids);
                 final Collection<ObjectAdapter> adapterList = adaptersByOid.values();
-                return _NullSafe.stream(adapterList)
+                return stream(adapterList)
                         .filter(_NullSafe::isPresent)
                         .collect(Collectors.toList());
             }
 
             private Iterable<ObjectAdapter> loadOneByOne(final EntityCollectionModel model) {
-                return _NullSafe.stream(model.mementoList)
+                return stream(model.mementoList)
                         .map(ObjectAdapterMemento.Functions.fromMemento(
                                 ConcurrencyChecking.NO_CHECK,
                                 model.getPersistenceSession(),


[isis] 05/08: ISIS-1976: decouple viewmodel re-creation from PersistenceSession

Posted by ah...@apache.org.
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 d3c46e8680309bec805efefb324fde304a3c6690
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Sep 10 12:47:03 2018 +0200

    ISIS-1976: decouple viewmodel re-creation from PersistenceSession
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../system/persistence/PersistenceSession4.java    | 49 +-----------
 .../system/persistence/PersistenceSession5.java    | 46 +----------
 .../system/persistence/PersistenceSession.java     |  2 -
 .../adaptermanager/ObjectAdapterContext.java       | 29 +++++--
 .../ObjectAdapterContext_DependencyInjection.java  | 88 ++++++++++++++++++++++
 .../ObjectAdapterContext_MementoSupport.java       |  2 +-
 ...ctAdapterContext_ObjectAdapterByIdProvider.java |  6 +-
 .../ObjectAdapterContext_ObjectReCreation.java     | 72 ++++++++++++++++++
 8 files changed, 191 insertions(+), 103 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 8af6150..1acd10d 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
@@ -459,58 +459,15 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final Object pojo;
 
         if(variant == Variant.VIEW_MODEL) {
-            pojo = recreateViewModel(spec, memento);
+            pojo = objectAdapterContext.recreateViewModel(spec, memento);
         } else {
-            pojo = instantiateAndInjectServices(spec);
-
+            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
         }
 
         final ObjectAdapter adapter = adapterFor(pojo);
         return initializePropertiesAndDoCallback(adapter);
     }
 
-    //FIXME[ISIS-1976] remove
-    private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
-        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
-        if(facet == null) {
-            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
-        }
-
-        final Object viewModelPojo;
-        if(facet.getRecreationMechanism().isInitializes()) {
-            viewModelPojo = instantiateAndInjectServices(spec);
-            facet.initialize(viewModelPojo, memento);
-        } else {
-            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
-        }
-        return viewModelPojo;
-    }
-
-    @Override
-    public Object instantiateAndInjectServices(final ObjectSpecification objectSpec) {
-
-        final Class<?> correspondingClass = objectSpec.getCorrespondingClass();
-        if (correspondingClass.isArray()) {
-            return Array.newInstance(correspondingClass.getComponentType(), 0);
-        }
-
-        final Class<?> cls = correspondingClass;
-        if (Modifier.isAbstract(cls.getModifiers())) {
-            throw new IsisException("Cannot create an instance of an abstract class: " + cls);
-        }
-
-        final Object newInstance;
-        try {
-            newInstance = cls.newInstance();
-        } catch (final IllegalAccessException | InstantiationException e) {
-            throw new IsisException("Failed to create instance of type " + objectSpec.getFullIdentifier(), e);
-        }
-
-        servicesInjector.injectServicesInto(newInstance);
-        return newInstance;
-
-    }
-
     private ObjectAdapter initializePropertiesAndDoCallback(final ObjectAdapter adapter) {
 
         // initialize new object
@@ -877,6 +834,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
         getTransactionManager().executeWithinTransaction(()->{
                 makePersistentTransactionAssumed(adapter);
+                // clear out the map of transient -> persistent
+                // already empty // PersistenceSession5.this.persistentByTransient.clear();
         });
     }
 
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 2e94fa3..3441cf0 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
@@ -457,9 +457,9 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final Object pojo;
 
         if(variant == Variant.VIEW_MODEL) {
-            pojo = recreateViewModel(spec, memento);
+            pojo = objectAdapterContext.recreateViewModel(spec, memento);
         } else {
-            pojo = instantiateAndInjectServices(spec);
+            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
 
         }
 
@@ -467,48 +467,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return initializePropertiesAndDoCallback(adapter);
     }
 
-    //FIXME[ISIS-1976] remove
-    private Object recreateViewModel(final ObjectSpecification spec, final String memento) {
-        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
-        if(facet == null) {
-            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
-        }
-
-        final Object viewModelPojo;
-        if(facet.getRecreationMechanism().isInitializes()) {
-            viewModelPojo = instantiateAndInjectServices(spec);
-            facet.initialize(viewModelPojo, memento);
-        } else {
-            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
-        }
-        return viewModelPojo;
-    }
-
-    @Override
-    public Object instantiateAndInjectServices(final ObjectSpecification objectSpec) {
-
-        final Class<?> correspondingClass = objectSpec.getCorrespondingClass();
-        if (correspondingClass.isArray()) {
-            return Array.newInstance(correspondingClass.getComponentType(), 0);
-        }
-
-        final Class<?> cls = correspondingClass;
-        if (Modifier.isAbstract(cls.getModifiers())) {
-            throw new IsisException("Cannot create an instance of an abstract class: " + cls);
-        }
-
-        final Object newInstance;
-        try {
-            newInstance = cls.newInstance();
-        } catch (final IllegalAccessException | InstantiationException e) {
-            throw new IsisException("Failed to create instance of type " + objectSpec.getFullIdentifier(), e);
-        }
-
-        servicesInjector.injectServicesInto(newInstance);
-        return newInstance;
-
-    }
-
     private ObjectAdapter initializePropertiesAndDoCallback(final ObjectAdapter adapter) {
 
         // initialize new object
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 b7a22f5..8f3967f 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
@@ -164,8 +164,6 @@ extends
     
     void execute(List<PersistenceCommand> persistenceCommandList);
 
-    Object instantiateAndInjectServices(ObjectSpecification spec);
-
     Object lookup(Bookmark bookmark, FieldResetPolicy fieldResetPolicy);
 
     void resolve(Object parent);
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 f4a21fa..efff6cc 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
@@ -31,12 +31,12 @@ import org.apache.isis.core.commons.ensure.IsisAssertException;
 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.concurrency.ConcurrencyChecking;
 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.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.spec.ObjectSpecId;
@@ -133,7 +133,9 @@ public class ObjectAdapterContext {
     private final ObjectAdapterContext_MementoSupport mementoSupportMixin;
     private final ObjectAdapterContext_ServiceLookup serviceLookupMixin;
     private final ObjectAdapterContext_NewIdentifier newIdentifierMixin;
-    private final ObjectAdapterContext_ObjectAdapterByIdProvider byIdMixin;
+    private final ObjectAdapterContext_ObjectAdapterByIdProvider objectAdapterByIdProviderMixin;
+    private final ObjectAdapterContext_DependencyInjection dependencyInjectionMixin;
+    private final ObjectAdapterContext_ObjectReCreation objectReCreationMixin;
     
     private ObjectAdapterContext(
             ServicesInjector servicesInjector, 
@@ -147,7 +149,9 @@ public class ObjectAdapterContext {
         this.mementoSupportMixin = new ObjectAdapterContext_MementoSupport(this, persistenceSession);
         this.serviceLookupMixin = new ObjectAdapterContext_ServiceLookup(this, servicesInjector);
         this.newIdentifierMixin = new ObjectAdapterContext_NewIdentifier(this, persistenceSession);
-        this.byIdMixin = new ObjectAdapterContext_ObjectAdapterByIdProvider(this, persistenceSession, authenticationSession);
+        this.objectAdapterByIdProviderMixin = new ObjectAdapterContext_ObjectAdapterByIdProvider(this, persistenceSession, authenticationSession);
+        this.dependencyInjectionMixin = new ObjectAdapterContext_DependencyInjection(this, persistenceSession);
+        this.objectReCreationMixin = new ObjectAdapterContext_ObjectReCreation(this, persistenceSession);
         
         this.persistenceSession = persistenceSession;
         this.servicesInjector = servicesInjector;
@@ -165,8 +169,7 @@ public class ObjectAdapterContext {
         if(LOG.isDebugEnabled()) {
             String id = Integer.toHexString(this.hashCode());
             String session = ""+persistenceSession;
-            System.out.println("!!!!!!!!!!!!!!!!!!!!!!! "+String.format("%s id=%s session='%s'", 
-                    msg, id, session));
+            LOG.debug(String.format("%s id=%s session='%s'", msg, id, session));
         }
     }
     
@@ -240,7 +243,13 @@ public class ObjectAdapterContext {
     // -- BY-ID SUPPORT
     
     public ObjectAdapterByIdProvider getObjectAdapterByIdProvider() {
-        return byIdMixin;
+        return objectAdapterByIdProviderMixin;
+    }
+    
+    // -- DEPENDENCY INJECTION
+    
+    public Object instantiateAndInjectServices(ObjectSpecification objectSpec) {
+        return dependencyInjectionMixin.instantiateAndInjectServices(objectSpec);
     }
     
     // -- FACTORIES
@@ -338,6 +347,12 @@ public class ObjectAdapterContext {
         return mementoSupportMixin;
     }
     
+    // -- OBJECT RECREATION SUPPORT
+    
+    public Object recreateViewModel(final ObjectSpecification spec, final String memento) {
+        return objectReCreationMixin.recreateViewModel(spec, memento);
+    }
+    
     // ------------------------------------------------------------------------------------------------
     
     public ObjectAdapter disposableAdapterForViewModel(Object viewModelPojo) {
@@ -477,7 +492,5 @@ public class ObjectAdapterContext {
 
 
 
-   
-
 
 }
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_DependencyInjection.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_DependencyInjection.java
new file mode 100644
index 0000000..edd51a2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_DependencyInjection.java
@@ -0,0 +1,88 @@
+/*
+ *  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 java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+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.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+/**
+ * package private mixin for ObjectAdapterContext
+ * <p>
+ * Responsibility: creates new domain object instances  
+ * </p> 
+ * @since 2.0.0-M2
+ */
+@SuppressWarnings("unused")
+class ObjectAdapterContext_DependencyInjection {
+    
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_DependencyInjection.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector;
+    private final SpecificationLoader specificationLoader;
+    
+    
+    ObjectAdapterContext_DependencyInjection(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+        this.specificationLoader = servicesInjector.getSpecificationLoader();
+    }
+    
+    Object instantiateAndInjectServices(final ObjectSpecification objectSpec) {
+
+        final Class<?> correspondingClass = objectSpec.getCorrespondingClass();
+        if (correspondingClass.isArray()) {
+            return Array.newInstance(correspondingClass.getComponentType(), 0);
+        }
+
+        final Class<?> cls = correspondingClass;
+        if (Modifier.isAbstract(cls.getModifiers())) {
+            throw new IsisException("Cannot create an instance of an abstract class: " + cls);
+        }
+
+        final Object newInstance;
+        try {
+            newInstance = cls.newInstance();
+        } catch (final IllegalAccessException | InstantiationException e) {
+            throw new IsisException("Failed to create instance of type " + objectSpec.getFullIdentifier(), e);
+        }
+
+        servicesInjector.injectServicesInto(newInstance);
+        return newInstance;
+
+    }
+    
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
index beaadae..f6ed879 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
@@ -72,7 +72,7 @@ class ObjectAdapterContext_MementoSupport implements MementoRecreateObjectSuppor
         
         if (spec.isParentedOrFreeCollection()) {
 
-            final Object recreatedPojo = persistenceSession.instantiateAndInjectServices(spec);
+            final Object recreatedPojo = objectAdapterContext.instantiateAndInjectServices(spec);
             adapter = objectAdapterContext.addRecreatedPojoToCache(oid, recreatedPojo);
             adapter = populateCollection(adapter, (CollectionData) data);
 
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 c4a8af3..3253e52 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
@@ -46,7 +46,7 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 /**
  * package private mixin for ObjectAdapterContext
  * <p>
- * Responsibility: creates RootOids 
+ * Responsibility: implements ObjectAdapterByIdProvider 
  * </p> 
  * @since 2.0.0-M2
  */
@@ -223,7 +223,7 @@ class ObjectAdapterContext_ObjectAdapterByIdProvider implements ObjectAdapterByI
             pojo = recreateViewModel(spec, memento);
 
         } else {
-            pojo = persistenceSession.instantiateAndInjectServices(spec);
+            pojo = objectAdapterContext.instantiateAndInjectServices(spec);
 
         }
         return pojo;
@@ -237,7 +237,7 @@ class ObjectAdapterContext_ObjectAdapterByIdProvider implements ObjectAdapterByI
 
         final Object viewModelPojo;
         if(facet.getRecreationMechanism().isInitializes()) {
-            viewModelPojo = persistenceSession.instantiateAndInjectServices(spec);
+            viewModelPojo = objectAdapterContext.instantiateAndInjectServices(spec);
             facet.initialize(viewModelPojo, memento);
         } else {
             viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java
new file mode 100644
index 0000000..cb276ac
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectReCreation.java
@@ -0,0 +1,72 @@
+/*
+ *  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.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+/**
+ * package private mixin for ObjectAdapterContext
+ * <p>
+ * Responsibility: re-creates domain object instances  
+ * </p> 
+ * @since 2.0.0-M2
+ */
+@SuppressWarnings("unused")
+class ObjectAdapterContext_ObjectReCreation {
+    
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_ObjectReCreation.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector;
+    private final SpecificationLoader specificationLoader;
+    
+    
+    ObjectAdapterContext_ObjectReCreation(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+        this.specificationLoader = servicesInjector.getSpecificationLoader();
+    }
+
+    Object recreateViewModel(final ObjectSpecification spec, final String memento) {
+        final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
+        if(facet == null) {
+            throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " + spec.getFullIdentifier());
+        }
+
+        final Object viewModelPojo;
+        if(facet.getRecreationMechanism().isInitializes()) {
+            viewModelPojo = objectAdapterContext.instantiateAndInjectServices(spec);
+            facet.initialize(viewModelPojo, memento);
+        } else {
+            viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), memento);
+        }
+        return viewModelPojo;
+    }
+    
+}
\ No newline at end of file