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 2020/12/25 19:22:17 UTC

[isis] branch master updated: ISIS-2033: dn-integration: further simplify, remove command queue

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new b53ace4  ISIS-2033: dn-integration: further simplify, remove command  queue
b53ace4 is described below

commit b53ace4bc11b9215e645e0699f1c6bae5c175e7c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 25 20:22:03 2020 +0100

    ISIS-2033: dn-integration: further simplify, remove command  queue
---
 .../command => lifecycles}/FetchResultHandler.java |   2 +-
 .../metamodel/facets/entity/JdoEntityFacet.java    |  88 +++++++++++--
 .../persistence/JdoPersistenceSession.java         |  35 -----
 .../persistence/JdoPersistenceSession5.java        | 145 +--------------------
 .../persistence/_JdoPersistenceSessionBase.java    |   2 +-
 .../persistence/command/CreateObjectCommand.java   |  55 --------
 .../persistence/command/DeleteObjectCommand.java   |  44 -------
 .../persistence/command/PersistenceCommand.java    |  30 -----
 .../transaction/TransactionalProcessor.java        |  10 +-
 .../transaction/TxManagerInternalFactory.java      |   2 +-
 .../transaction/_PersistenceCommandQueue.java      | 145 ---------------------
 .../jdo/integration/transaction/_Tx.java           |  42 ------
 .../jdo/integration/transaction/_TxHelper.java     |  15 ---
 .../transaction/_TxManagerInternal.java            |  22 +---
 14 files changed, 92 insertions(+), 545 deletions(-)

diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/FetchResultHandler.java
similarity index 93%
rename from persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java
rename to persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/FetchResultHandler.java
index b490301..8850c6b 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/FetchResultHandler.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/lifecycles/FetchResultHandler.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.persistence.jdo.integration.persistence.command;
+package org.apache.isis.persistence.jdo.integration.lifecycles;
 
 import org.datanucleus.enhancement.Persistable;
 
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
index 3c06855..cdfadd0 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/metamodel/facets/entity/JdoEntityFacet.java
@@ -20,12 +20,15 @@ package org.apache.isis.persistence.jdo.integration.metamodel.facets.entity;
 
 import java.lang.reflect.Method;
 
+import javax.jdo.FetchGroup;
+
 import org.datanucleus.enhancement.Persistable;
 import org.datanucleus.store.rdbms.RDBMSPropertyNames;
 
 import org.apache.isis.applib.query.AllInstancesQuery;
 import org.apache.isis.applib.query.NamedQuery;
 import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.repository.EntityState;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.assertions._Assert;
@@ -34,6 +37,8 @@ import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.interaction.session.InteractionTracker;
+import org.apache.isis.core.metamodel.adapter.oid.ObjectNotFoundException;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.entity.EntityFacet;
@@ -44,6 +49,7 @@ import org.apache.isis.persistence.jdo.datanucleus.oid.JdoObjectIdSerializer;
 import org.apache.isis.persistence.jdo.integration.metamodel.JdoMetamodelUtil;
 import org.apache.isis.persistence.jdo.integration.persistence.JdoPersistenceSession;
 
+import lombok.NonNull;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -95,12 +101,49 @@ implements EntityFacet {
     }
     
     @Override
-    public ManagedObject fetchByIdentifier(ObjectSpecification spec, String identifier) {
+    public ManagedObject fetchByIdentifier(
+            final @NonNull ObjectSpecification entitySpec, 
+            final @NonNull String identifier) {
         
-        if(!spec.isEntity()) {
-            throw _Exceptions.unexpectedCodeReach();
+        _Assert.assertTrue(entitySpec.isEntity());
+        
+        val rootOid = Oid.Factory.root(entitySpec.getSpecId(), identifier);
+        
+        log.debug("fetchEntity; rootOid={}", rootOid);
+
+        Object entityPojo;
+        try {
+            val primaryKey = JdoObjectIdSerializer.toJdoObjectId(entitySpec, rootOid);
+            val persistenceManager = getJdoPersistenceSession().getPersistenceManager();
+            val entityClass = entitySpec.getCorrespondingClass();
+            val fetchPlan = persistenceManager.getFetchPlan();
+            fetchPlan.addGroup(FetchGroup.DEFAULT);
+            entityPojo = persistenceManager.getObjectById(entityClass, primaryKey);
+            
+        } catch (final RuntimeException e) {
+
+            //XXX this idiom could be delegated to a service
+            //or remodel the method to return a Result<T>
+            for (val exceptionRecognizer : getMetaModelContext().getServiceRegistry()
+                    .select(ExceptionRecognizer.class)) {
+                val recognition = exceptionRecognizer.recognize(e).orElse(null);
+                if(recognition != null) {
+                    if(recognition.getCategory() == ExceptionRecognizer.Category.NOT_FOUND) {
+                        throw new ObjectNotFoundException(rootOid, e);
+                    }
+                }
+            }
+
+            throw e;
         }
-        return getJdoPersistenceSession().fetchByIdentifier(spec, identifier);
+
+        if (entityPojo == null) {
+            throw new ObjectNotFoundException(rootOid);
+        }
+        
+        val actualEntitySpec = getSpecificationLoader().loadSpecification(entityPojo.getClass());
+        getServiceInjector().injectServicesInto(entityPojo); // might be redundant
+        return ManagedObject.identified(actualEntitySpec, entityPojo, rootOid);
     }
     
     @Override
@@ -131,7 +174,7 @@ implements EntityFacet {
             
             val resultList = getJdoPersistenceSession()
                    .getTransactionalProcessor()
-                   .executeWithinTransaction(typedQuery::executeList);
+                   .fetchWithinTransaction(typedQuery::executeList);
             
             if(range.hasLimit()) {
                 _Assert.assertTrue(resultList.size()<=range.getLimit());
@@ -171,7 +214,7 @@ implements EntityFacet {
             
             val resultList = getJdoPersistenceSession()
                     .getTransactionalProcessor()
-                    .executeWithinTransaction(namedQuery::executeList);
+                    .fetchWithinTransaction(namedQuery::executeList);
             
             if(range.hasLimit()) {
                 _Assert.assertTrue(resultList.size()<=range.getLimit());
@@ -186,18 +229,43 @@ implements EntityFacet {
     }
 
     @Override
-    public void persist(ObjectSpecification spec, Object pojo) {
+    public void persist(final ObjectSpecification spec, final Object pojo) {
 
         if(pojo==null || !isPersistableType(pojo.getClass())) {
             return; //noop
         }
         
-        getJdoPersistenceSession().makePersistentInTransaction(ManagedObject.of(spec, pojo));
+        if (DnEntityStateProvider.entityState(pojo).isAttached()) {
+            return; //noop
+        }
+        
+        val pm = getJdoPersistenceSession().getPersistenceManager();
+        
+        log.debug("about to persist entity {}", pojo);
+        
+        getJdoPersistenceSession()
+        .getTransactionalProcessor().doWithinTransaction(()->pm.makePersistent(pojo));
+        
     }
     
     @Override
-    public void delete(ObjectSpecification spec, Object pojo) {
-        getJdoPersistenceSession().destroyObjectInTransaction(ManagedObject.of(spec, pojo));
+    public void delete(final ObjectSpecification spec, final Object pojo) {
+        
+        if(pojo==null || !isPersistableType(pojo.getClass())) {
+            return; //noop
+        }
+        
+        if (!DnEntityStateProvider.entityState(pojo).isAttached()) {
+            throw _Exceptions.illegalArgument("can only delete an attached entity");
+        }
+        
+        val pm = getJdoPersistenceSession().getPersistenceManager();
+        
+        log.debug("about to delete entity {}", pojo);
+        
+        getJdoPersistenceSession()
+        .getTransactionalProcessor().doWithinTransaction(()->pm.deletePersistent(pojo));
+        
     }
     
     @Override
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession.java
index 9e04ce6..34b655e 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession.java
@@ -18,11 +18,7 @@
  */
 package org.apache.isis.persistence.jdo.integration.persistence;
 
-import java.rmi.NoSuchObjectException;
-
 import org.apache.isis.core.metamodel.context.HasMetaModelContext;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.persistence.jdo.integration.transaction.TransactionalProcessor;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
@@ -45,35 +41,4 @@ extends
      */
     void refreshEntity(Object pojo);
 
-    /**
-     * @since 2.0
-     * @throws NoSuchObjectException if not found
-     */
-    ManagedObject fetchByIdentifier(ObjectSpecification spec, String identifier);
-
-    /**
-     * Removes the specified object from the system. The specified object's data
-     * should be removed from the persistence mechanism.
-     */
-    void destroyObjectInTransaction(ManagedObject adapter);
-    
-    /**
-     * Makes an {@link ManagedObject} persistent. The specified object should be
-     * stored away via this object store's persistence mechanism, and have a
-     * new and unique OID assigned to it. The object, should also be added to
-     * the {@link JdoPersistenceSession} as the object is implicitly 'in use'.
-     *
-     * <p>
-     * If the object has any associations then each of these, where they aren't
-     * already persistent, should also be made persistent by recursively calling
-     * this method.
-     *
-     * <p>
-     * If the object to be persisted is a collection, then each element of that
-     * collection, that is not already persistent, should be made persistent by
-     * recursively calling this method.
-     */
-    void makePersistentInTransaction(ManagedObject adapter);
-
-
 }
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
index edaf5f9..5c3e5da 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/JdoPersistenceSession5.java
@@ -20,31 +20,22 @@ package org.apache.isis.persistence.jdo.integration.persistence;
 
 import javax.annotation.Nullable;
 import javax.enterprise.inject.Vetoed;
-import javax.jdo.FetchGroup;
 import javax.jdo.PersistenceManager;
 import javax.jdo.PersistenceManagerFactory;
 
 import org.datanucleus.enhancement.Persistable;
 
-import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
-import org.apache.isis.core.metamodel.adapter.oid.ObjectNotFoundException;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.PojoRefreshException;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.transaction.integration.IsisTransactionObject;
-import org.apache.isis.persistence.jdo.applib.exceptions.NotPersistableException;
 import org.apache.isis.persistence.jdo.applib.fixturestate.FixturesInstalledStateHolder;
 import org.apache.isis.persistence.jdo.datanucleus.entities.DnEntityStateProvider;
-import org.apache.isis.persistence.jdo.datanucleus.oid.JdoObjectIdSerializer;
+import org.apache.isis.persistence.jdo.integration.lifecycles.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.lifecycles.IsisLifecycleListener;
 import org.apache.isis.persistence.jdo.integration.lifecycles.JdoStoreLifecycleListenerForIsis;
 import org.apache.isis.persistence.jdo.integration.lifecycles.LoadLifecycleListenerForIsis;
-import org.apache.isis.persistence.jdo.integration.persistence.command.CreateObjectCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.command.DeleteObjectCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.transaction.TransactionalProcessor;
 
 import lombok.NonNull;
@@ -159,55 +150,6 @@ implements
         return txCommandProcessor;
     }
 
-    // -- FETCHING
-
-    @Override
-    public ManagedObject fetchByIdentifier(
-            final @NonNull ObjectSpecification spec, 
-            final @NonNull String identifier) {
-
-        val rootOid = Oid.Factory.root(spec.getSpecId(), identifier);
-        
-        log.debug("fetchEntity; oid={}", rootOid);
-        
-        val entity = fetchEntity(spec, rootOid); // throws if null
-        
-        return ManagedObject.identified(spec, entity, rootOid);
-    }
-    
-    private Object fetchEntity(final ObjectSpecification spec, final RootOid rootOid) {
-
-        Object result;
-        try {
-            val cls = spec.getCorrespondingClass();
-            val jdoObjectId = JdoObjectIdSerializer.toJdoObjectId(spec, rootOid);
-            val fetchPlan = persistenceManager.getFetchPlan();
-            fetchPlan.addGroup(FetchGroup.DEFAULT);
-            result = persistenceManager.getObjectById(cls, jdoObjectId);
-        } catch (final RuntimeException e) {
-
-            //XXX this idiom could be delegated to a service
-            //or remodel the method to return a Result<T>
-            for (val exceptionRecognizer : getMetaModelContext().getServiceRegistry()
-                    .select(ExceptionRecognizer.class)) {
-                val recognition = exceptionRecognizer.recognize(e).orElse(null);
-                if(recognition != null) {
-                    if(recognition.getCategory() == ExceptionRecognizer.Category.NOT_FOUND) {
-                        throw new ObjectNotFoundException(rootOid, e);
-                    }
-                }
-            }
-
-            throw e;
-        }
-
-        if (result == null) {
-            throw new ObjectNotFoundException(rootOid);
-        }
-
-        return result;
-    }
-
     // -- REFRESH
 
     @Override
@@ -236,91 +178,6 @@ implements
         initializeEntityAfterFetched((Persistable) domainObject);
     }
 
-    // -- makePersistent
-
-
-    @Override
-    public void makePersistentInTransaction(final ManagedObject entity) {
-        
-        log.debug("about to persist entity {}", entity);
-        state.ensureOpened();
-        
-        val pojo = entity.getPojo();
-        
-        if (DnEntityStateProvider.entityState(pojo).isAttached()) {
-            throw new NotPersistableException("Object already persistent: " + entity);
-        }
-        val spec = entity.getSpecification();
-        if (spec.isManagedBean()) {
-            throw new NotPersistableException("Can only persist entity beans: "+ entity);
-        }
-        if (spec.getBeanSort().isCollection()) {
-            //XXX not sure if we can do better than that, eg. traverse each element of the collection and persist individually
-            throw new NotPersistableException("Cannot persist a collection: " + entity);
-        }
-        
-        txCommandProcessor.executeWithinTransaction(newCreateObjectCommand(entity));
-    }
-    
-    // -- destroyObjectInTransaction
-
-    @Override
-    public void destroyObjectInTransaction(final ManagedObject entity) {
-        
-        val spec = entity.getSpecification();
-        if (spec.isParented()) {
-            return;
-        }
-        
-        log.debug("about to delete entity {}", entity);
-        state.ensureOpened();
-        
-        txCommandProcessor.executeWithinTransaction(newDeleteObjectCommand(entity));
-    }
-
-    // -- newXxxCommand
-    /**
-     * Makes an {@link ObjectAdapter} persistent. The specified object should be
-     * stored away via this object store's persistence mechanism, and have an
-     * new and unique OID assigned to it (by calling the object's
-     * <code>setOid</code> method). The object, should also be added to the
-     * cache as the object is implicitly 'in use'.
-     *
-     * <p>
-     * If the object has any associations then each of these, where they aren't
-     * already persistent, should also be made persistent by recursively calling
-     * this method.
-     * </p>
-     *
-     * <p>
-     * If the object to be persisted is a collection, then each element of that
-     * collection, that is not already persistent, should be made persistent by
-     * recursively calling this method.
-     * </p>
-     *
-     */
-    private CreateObjectCommand newCreateObjectCommand(final ManagedObject adapter) {
-
-        val pojo = adapter.getPojo();
-
-        log.debug("create object - creating command for: {}", adapter);
-        if (DnEntityStateProvider.entityState(pojo).isAttached()) {
-            throw new IllegalArgumentException("Adapter is persistent; adapter: " + adapter);
-        }
-        return new CreateObjectCommand(adapter);
-    }
-
-    private DeleteObjectCommand newDeleteObjectCommand(final ManagedObject adapter) {
-        
-        val pojo = adapter.getPojo();
-
-        log.debug("destroy object - creating command for: {}", adapter);
-        if (!DnEntityStateProvider.entityState(pojo).isAttached()) {
-            throw new IllegalArgumentException("Adapter is not persistent; adapter: " + adapter);
-        }
-        return new DeleteObjectCommand(adapter);
-    }
-
     // -- FrameworkSynchronizer delegate methods
 
     @Override
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
index a37eea8..f25875c 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/_JdoPersistenceSessionBase.java
@@ -28,7 +28,7 @@ import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.transaction.changetracking.EntityChangeTracker;
 import org.apache.isis.persistence.jdo.applib.fixturestate.FixturesInstalledStateHolder;
-import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
+import org.apache.isis.persistence.jdo.integration.lifecycles.FetchResultHandler;
 import org.apache.isis.persistence.jdo.integration.transaction.TransactionalProcessor;
 import org.apache.isis.persistence.jdo.integration.transaction.TxManagerInternalFactory;
 
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/CreateObjectCommand.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/CreateObjectCommand.java
deleted file mode 100644
index 5b7b37c..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/CreateObjectCommand.java
+++ /dev/null
@@ -1,55 +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.persistence.jdo.integration.persistence.command;
-
-import javax.jdo.PersistenceManager;
-
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.persistence.jdo.datanucleus.entities.DnEntityStateProvider;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.ToString;
-import lombok.val;
-import lombok.extern.log4j.Log4j2;
-
-@RequiredArgsConstructor @ToString
-@Log4j2
-public class CreateObjectCommand implements PersistenceCommand {
-
-    @Getter private final ManagedObject entity;
-
-    @Override
-    public void execute(PersistenceManager persistenceManager) {
-        if (log.isDebugEnabled()) {
-            log.debug("create object - executing command for: {}", entity);
-        }
-        
-        val domainObject = entity.getPojo();
-        if(!DnEntityStateProvider.entityState(domainObject).isDetached()) {
-            // this could happen if DN's persistence-by-reachability has already caused the domainobject
-            // to be persisted.  It's Isis adapter will have been updated as a result of the postStore
-            // lifecycle callback, so in essence there's nothing to be done.
-            return;
-        }
-
-        persistenceManager.makePersistent(domainObject);
-    }
-
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/DeleteObjectCommand.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/DeleteObjectCommand.java
deleted file mode 100644
index a3351ae..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/DeleteObjectCommand.java
+++ /dev/null
@@ -1,44 +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.persistence.jdo.integration.persistence.command;
-
-import javax.jdo.PersistenceManager;
-
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.ToString;
-import lombok.extern.log4j.Log4j2;
-
-@RequiredArgsConstructor @ToString
-@Log4j2
-public class DeleteObjectCommand implements PersistenceCommand {
-
-    @Getter private final ManagedObject entity;
-    
-    @Override
-    public void execute(PersistenceManager persistenceManager) {
-        if (log.isDebugEnabled()) {
-            log.debug("delete object - executing command for {}", entity);
-        }
-        persistenceManager.deletePersistent(entity.getPojo());
-    }
-
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/PersistenceCommand.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/PersistenceCommand.java
deleted file mode 100644
index 1643dec..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/persistence/command/PersistenceCommand.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.persistence.jdo.integration.persistence.command;
-
-import javax.jdo.PersistenceManager;
-
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-
-public interface PersistenceCommand {
-
-    void execute(PersistenceManager persistenceManager);
-    ManagedObject getEntity();
-
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalProcessor.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalProcessor.java
index 7fdfe7b..45d3c71 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalProcessor.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TransactionalProcessor.java
@@ -22,17 +22,13 @@ import java.util.List;
 import java.util.function.Supplier;
 
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.functional.ThrowingRunnable;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
 
 public interface TransactionalProcessor {
 
-    void executeWithinTransaction(PersistenceCommand persistenceCommand);
+    Can<ManagedObject> fetchWithinTransaction(Supplier<List<?>> fetcher);
 
-    Can<ManagedObject> executeWithinTransaction(Supplier<List<?>> fetcher);
-    
-    
-    //void createObject(ManagedObject adapter);
-    //void deleteObject(ManagedObject adapter);
+    void doWithinTransaction(ThrowingRunnable runnable);
     
 }
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
index b07b625..32bfb8a 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/TxManagerInternalFactory.java
@@ -20,7 +20,7 @@ package org.apache.isis.persistence.jdo.integration.transaction;
 
 import org.apache.isis.core.interaction.session.InteractionTracker;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
-import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
+import org.apache.isis.persistence.jdo.integration.lifecycles.FetchResultHandler;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
 import lombok.val;
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_PersistenceCommandQueue.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_PersistenceCommandQueue.java
deleted file mode 100644
index 2b2c406..0000000
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_PersistenceCommandQueue.java
+++ /dev/null
@@ -1,145 +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.persistence.jdo.integration.transaction;
-
-import java.util.function.Consumer;
-
-import javax.annotation.Nullable;
-
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.collections._Inbox;
-import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.persistence.jdo.integration.persistence.command.CreateObjectCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.command.DeleteObjectCommand;
-import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
-
-import lombok.NonNull;
-import lombok.val;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-final class _PersistenceCommandQueue {
-
-    private final _Inbox<PersistenceCommand> persistenceCommands = new _Inbox<>();
-
-    /**
-     * Add the non-null command to the list of commands to execute at the end of
-     * the transaction.
-     */
-    public void append(final @Nullable PersistenceCommand command) {
-        if (command == null) {
-            return;
-        }
-
-        final ManagedObject entity = command.getEntity();
-
-        // Destroys are ignored when preceded by a create, or another destroy
-        if (command instanceof DeleteObjectCommand) {
-            if (alreadyHasCreate(entity)) {
-                removeCreate(entity);
-                if (log.isDebugEnabled()) {
-                    log.debug("ignored both create and destroy command {}", command);
-                }
-                return;
-            }
-
-            if (alreadyHasDestroy(entity)) {
-                if (log.isDebugEnabled()) {
-                    log.debug("ignored command {} as command already recorded", command);
-                }
-                return;
-            }
-        }
-
-        log.debug("add command {}", command);
-        persistenceCommands.add(command);
-    }
-    
-    public void drain(final @NonNull Consumer<Can<PersistenceCommand>> onMoreCommands) {
-
-        //
-        // it's possible that in executing these commands that more will be created.
-        // so we keep flushing until no more are available (ISIS-533)
-        //
-        // this is a do...while rather than a while... just for backward compatibility
-        // with previous algorithm that always went through the execute phase at least once.
-        //
-        do {
-            // this algorithm ensures that we never execute the same command twice,
-            // and also allow new commands to be added to end
-            val pc_snapshot = persistenceCommands.snapshotThenClear();
-
-            if(!pc_snapshot.isEmpty()) {
-                try {
-                    
-                    onMoreCommands.accept(pc_snapshot);
-                    
-                } catch (RuntimeException ex) {
-                    // if there's an exception, we want to make sure that
-                    // all commands are cleared and propagate
-                    persistenceCommands.clear();
-                    throw ex;
-                }
-            }
-        } while(!persistenceCommands.isEmpty());
-
-    }
-    
-    @Override
-    public String toString() {
-        return String.format("CommandQueue[%s]", persistenceCommands.snapshot());
-    }
-    
-    // -- HELPER
-    
-    private boolean alreadyHasCommand(final Class<?> commandClass, final ManagedObject onObject) {
-        return getCommand(commandClass, onObject) != null;
-    }
-
-    private boolean alreadyHasCreate(final ManagedObject onObject) {
-        return alreadyHasCommand(CreateObjectCommand.class, onObject);
-    }
-
-    private boolean alreadyHasDestroy(final ManagedObject onObject) {
-        return alreadyHasCommand(DeleteObjectCommand.class, onObject);
-    }
-
-    private PersistenceCommand getCommand(final Class<?> commandClass, final ManagedObject entity) {
-        for (final PersistenceCommand command : persistenceCommands.snapshot()) {
-            if (command.getEntity().equals(entity)) {
-                if (commandClass.isAssignableFrom(command.getClass())) {
-                    return command;
-                }
-            }
-        }
-        return null;
-    }
-
-    private void removeCommand(final Class<?> commandClass, final ManagedObject onObject) {
-        final PersistenceCommand toDelete = getCommand(commandClass, onObject);
-        persistenceCommands.remove(toDelete);
-    }
-
-    private void removeCreate(final ManagedObject onObject) {
-        removeCommand(CreateObjectCommand.class, onObject);
-    }
-    
-
-    
-}
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_Tx.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_Tx.java
index aee2fbf..2c9b856 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_Tx.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_Tx.java
@@ -22,7 +22,6 @@ package org.apache.isis.persistence.jdo.integration.transaction;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 
-import javax.annotation.Nullable;
 import javax.enterprise.inject.Vetoed;
 
 import org.apache.isis.applib.annotation.Programmatic;
@@ -40,7 +39,6 @@ import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.transaction.integration.IsisTransactionFlushException;
 import org.apache.isis.core.transaction.integration.IsisTransactionManagerException;
 import org.apache.isis.persistence.jdo.integration.persistence.JdoPersistenceSession;
-import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -155,8 +153,6 @@ class _Tx implements Transaction {
     @ToString.Exclude
     private final _TxHelper txHelper;
     
-    private final _PersistenceCommandQueue commandQueue;
-    
     @ToString.Exclude
     private final InteractionTracker isisInteractionTracker;
 
@@ -174,7 +170,6 @@ class _Tx implements Transaction {
         id = TransactionId.of(interactionId, sequence);
         
         this.txHelper = txHelper;
-        this.commandQueue = new _PersistenceCommandQueue();
         this.isisInteractionTracker = mmc.getServiceRegistry().lookupServiceElseFail(InteractionTracker.class);
         this.transactionScopeListeners = mmc.getServiceRegistry().select(TransactionScopeListener.class);
 
@@ -217,16 +212,6 @@ class _Tx implements Transaction {
                 : transactionState;
     }
 
-    // -- commands
-
-    /**
-     * Add the non-null command to the list of commands to execute at the end of
-     * the transaction.
-     */
-    public void addCommand(final @Nullable PersistenceCommand command) {
-        commandQueue.append(command);
-    }
-
     // -- flush
 
     @Override
@@ -242,38 +227,12 @@ class _Tx implements Transaction {
         log.debug("flush transaction {}", this);
 
         try {
-            flushCommands();
             flushTransaction();
         } catch (final RuntimeException ex) {
             setAbortCause(new IsisTransactionFlushException(ex));
             throw ex;
         }
     }
-
-    /**
-     * Called by {@link #preCommit()} and {@link #flush()}:
-     * <p>
-     * <table>
-     * <tr>
-     * <th>called from</th>
-     * <th>next {@link #getState() state} if ok</th>
-     * <th>next {@link #getState() state} if exception</th>
-     * </tr>
-     * <tr>
-     * <td>{@link #commit()}</td>
-     * <td>{@link State#COMMITTED}</td>
-     * <td>{@link State#ABORTED}</td>
-     * </tr>
-     * <tr>
-     * <td>{@link #flush()}</td>
-     * <td>{@link State#IN_PROGRESS}</td>
-     * <td>{@link State#MUST_ABORT}</td>
-     * </tr>
-     * </table>
-     */
-    private void flushCommands() {
-        commandQueue.drain(txHelper::execute);
-    }
     
     private void flushTransaction() {
         txHelper.flushTransaction();
@@ -301,7 +260,6 @@ class _Tx implements Transaction {
 
         try {
             
-            flushCommands();
             flushTransaction();
             
             notifyPreCommit(PreCommitPhase.PRE_PUBLISHING);
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxHelper.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxHelper.java
index 75ac85b..e51255f 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxHelper.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxHelper.java
@@ -20,11 +20,9 @@ package org.apache.isis.persistence.jdo.integration.transaction;
 
 import javax.jdo.PersistenceManager;
 
-import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
 import lombok.NonNull;
-import lombok.val;
 
 interface _TxHelper extends HasPersistenceManager {
     
@@ -77,17 +75,4 @@ interface _TxHelper extends HasPersistenceManager {
         }
     }
     
-    default void execute(final Iterable<PersistenceCommand> commands) {
-
-        // previously we used to check that there were some commands, and skip processing otherwise.
-        // we no longer do that; it could be (is quite likely) that DataNucleus has some dirty objects anyway that
-        // don't have commands wrapped around them...
-
-        val pm = getPersistenceManager();
-        for (val command : commands) {
-            command.execute(pm);
-        }
-        pm.flush();
-    }
-    
 }
diff --git a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
index b34852a..46b9f7a 100644
--- a/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
+++ b/persistence/jdo/integration/src/main/java/org/apache/isis/persistence/jdo/integration/transaction/_TxManagerInternal.java
@@ -30,6 +30,7 @@ import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.exceptions.IsisException;
+import org.apache.isis.commons.functional.ThrowingRunnable;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -37,8 +38,7 @@ import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.transaction.integration.IsisTransactionAspectSupport;
 import org.apache.isis.core.transaction.integration.IsisTransactionManagerException;
 import org.apache.isis.core.transaction.integration.IsisTransactionObject;
-import org.apache.isis.persistence.jdo.integration.persistence.command.FetchResultHandler;
-import org.apache.isis.persistence.jdo.integration.persistence.command.PersistenceCommand;
+import org.apache.isis.persistence.jdo.integration.lifecycles.FetchResultHandler;
 import org.apache.isis.persistence.jdo.provider.persistence.HasPersistenceManager;
 
 import lombok.val;
@@ -326,22 +326,15 @@ implements
             txObject.clear();
         }
     }
-
+    
     @Override
-    public void executeWithinTransaction(PersistenceCommand command) {
-        mmc.getTransactionService().executeWithinTransaction(()->{
-        
-            val transaction = getCurrentTransaction();
-            if (transaction != null && command != null) {
-                transaction.addCommand(command);
-            }
-            
-        })
-        .nullableOrElseFail();
+    public void doWithinTransaction(ThrowingRunnable runnable) {
+        mmc.getTransactionService().executeWithinTransaction(runnable)
+                .nullableOrElseFail();
     }
     
     @Override
-    public Can<ManagedObject> executeWithinTransaction(Supplier<List<?>> fetcher) {
+    public Can<ManagedObject> fetchWithinTransaction(Supplier<List<?>> fetcher) {
         final Can<ManagedObject> instances = mmc.getTransactionService().executeWithinTransaction(
                 ()->_NullSafe.stream(fetcher.get())
                     .map(this::adopt)
@@ -376,5 +369,4 @@ implements
 
 
 
-
 }