You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/07/06 12:36:06 UTC

[isis] 01/11: ISIS-2789: sketches implementation.

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

danhaywood pushed a commit to branch ISIS-2789
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 07a893ac69177e182954530e42374ffa9b932e56
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jul 2 15:36:48 2021 +0100

    ISIS-2789: sketches implementation.
    
    However, I find that the EntityChangeTrackerDefault that is queried for snapshots at end of interaction is a different instance to the one in which changes are enlisted (for an initial persist).  Unsurprisingly, we get no entity property changes published.  Is there an issue with @InteractionScope (InteractionScopeLifecycleHandler)
---
 .../core/interaction/scope/InteractionScope.java   |   4 +-
 .../changetracking/EntityChangeTrackerDefault.java |   3 +-
 persistence/jpa/applib/pom.xml                     |  12 ++-
 .../jpa/applib/integration/IsisEntityListener.java | 112 +++++++++++++++++++++
 .../JpaEntityInjectionPointResolver.java           |  48 +--------
 .../util/interaction/InteractionBoundaryProbe.java |   6 +-
 6 files changed, 132 insertions(+), 53 deletions(-)

diff --git a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
index 808562c..3eed6fa 100644
--- a/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
+++ b/core/interaction/src/main/java/org/apache/isis/core/interaction/scope/InteractionScope.java
@@ -49,7 +49,7 @@ class InteractionScope implements Scope, InteractionScopeLifecycleHandler {
         Object instance;
         Runnable destructionCallback;
         void preDestroy() {
-            log.debug("destroy isis-session scoped {}", name);
+            log.debug("destroy isis-interaction scoped {}", name);
             if(destructionCallback!=null) {
                 destructionCallback.run();
             }
@@ -81,7 +81,7 @@ class InteractionScope implements Scope, InteractionScopeLifecycleHandler {
         val newScopedObject = ScopedObject.of(name);
         scopedObjects.get().put(name, newScopedObject); // just set a stub with a name only
 
-        log.debug("create new isis-session scoped {}", name);
+        log.debug("create new isis-interaction scoped {}", name);
         newScopedObject.setInstance(objectFactory.getObject()); // triggers call to registerDestructionCallback
 
         return newScopedObject.getInstance();
diff --git a/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java b/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
index 208f847..ce2f01a 100644
--- a/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
+++ b/core/transaction/src/main/java/org/apache/isis/core/transaction/changetracking/EntityChangeTrackerDefault.java
@@ -32,6 +32,7 @@ import javax.inject.Provider;
 
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.event.EventListener;
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.EntityChangeKind;
@@ -174,7 +175,7 @@ implements
      * TRANSACTION END BOUNDARY
      * @apiNote intended to be called during before transaction completion by the framework internally
      */
-    @EventListener(value = TransactionBeforeCompletionEvent.class)
+    @EventListener(value = TransactionBeforeCompletionEvent.class) @Order(PriorityPrecedence.LATE)
     public void onTransactionCompleting(TransactionBeforeCompletionEvent event) {
         try {
             doPublish();
diff --git a/persistence/jpa/applib/pom.xml b/persistence/jpa/applib/pom.xml
index a07b8f0..f9be8c0 100644
--- a/persistence/jpa/applib/pom.xml
+++ b/persistence/jpa/applib/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
-	license agreements. See the NOTICE file distributed with this work for additional 
+<!-- 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 
@@ -77,7 +77,13 @@
 			<artifactId>isis-commons</artifactId>
 		</dependency>
 
-		<!-- TODO JPA API (providing compile dependency) -->
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-transaction</artifactId>
+			<scope>provided</scope>
+        </dependency>
+
+        <!-- TODO JPA API (providing compile dependency) -->
 
 
 	</dependencies>
diff --git a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/IsisEntityListener.java b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/IsisEntityListener.java
new file mode 100644
index 0000000..a9b0af2
--- /dev/null
+++ b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/IsisEntityListener.java
@@ -0,0 +1,112 @@
+/*
+ *  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.jpa.applib.integration;
+
+import javax.inject.Inject;
+import javax.persistence.PostLoad;
+import javax.persistence.PostPersist;
+import javax.persistence.PostRemove;
+import javax.persistence.PostUpdate;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+
+import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
+import org.apache.isis.core.transaction.changetracking.EntityChangeTracker;
+
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
+
+/**
+ * EntityListener class for listing with the {@link javax.persistence.EntityListeners} annotation, to
+ * support injection point resolving for entities, and to notify {@link EntityChangeTracker} of changes.
+ *
+ * <p>
+ * Instances of this class are not managed by Spring, but by the persistence layer.
+ * </p>
+ *
+ * <p>
+ * The particular persistence layer implementation in use needs to be configured,
+ * with a BeanManager, that is able to resolve injection points for this EntityListener.
+ * </p>
+ *
+ * @since 2.0 {@index}
+ */
+@Log4j2
+public class IsisEntityListener {
+
+    // not managed by Spring (directly)
+    @Inject private ServiceInjector serviceInjector;
+    @Inject private EntityChangeTracker entityChangeTracker;
+    @Inject private ObjectManager objectManager;
+
+
+    @PrePersist
+    private void onPrePersist(Object entityPojo) {
+        log.debug("onPrePersist: {}", entityPojo);
+        serviceInjector.injectServicesInto(entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.recognizePersisting(entity);
+    }
+
+    @PreUpdate
+    private void onPreUpdate(Object entityPojo) {
+        log.debug("onPreUpdate: {}", entityPojo);
+        serviceInjector.injectServicesInto(entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.enlistUpdating(entity);
+    }
+
+    @PreRemove
+    private void onPreRemove(Object entityPojo) {
+        log.debug("onAnyRemove: {}", entityPojo);
+        serviceInjector.injectServicesInto(entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.enlistDeleting(entity);
+    }
+
+    @PostPersist
+    private void onPostPersist(Object entityPojo) {
+        log.debug("onPostPersist: {}", entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.enlistCreated(entity);
+    }
+
+    @PostUpdate
+    private void onPostUpdate(Object entityPojo) {
+        log.debug("onPostUpdate: {}", entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.recognizeUpdating(entity);
+    }
+
+    @PostRemove
+    private void onPostRemove(Object entityPojo) {
+        log.debug("onPostRemove: {}", entityPojo);
+    }
+
+    @PostLoad
+    private void onPostLoad(Object entityPojo) {
+        log.debug("onPostLoad: {}", entityPojo);
+        serviceInjector.injectServicesInto(entityPojo);
+        val entity = objectManager.adapt(entityPojo);
+        entityChangeTracker.recognizeLoaded(entity);
+    }
+
+}
diff --git a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/JpaEntityInjectionPointResolver.java b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/JpaEntityInjectionPointResolver.java
index b6d5085..607af96 100644
--- a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/JpaEntityInjectionPointResolver.java
+++ b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/integration/JpaEntityInjectionPointResolver.java
@@ -18,55 +18,13 @@
  */
 package org.apache.isis.persistence.jpa.applib.integration;
 
-import javax.inject.Inject;
-import javax.persistence.PostLoad;
-import javax.persistence.PostPersist;
-import javax.persistence.PostRemove;
-import javax.persistence.PostUpdate;
-import javax.persistence.PrePersist;
-import javax.persistence.PreRemove;
-import javax.persistence.PreUpdate;
-
-import org.apache.isis.applib.services.inject.ServiceInjector;
-
 import lombok.extern.log4j.Log4j2;
 
 /**
- * EntityListener class for listing with the {@link javax.persistence.EntityListeners} annotation, to
- * support injection point resolving for entities.
- * <p>
- * Instances of this class are not managed by Spring, but by the persistence layer.
- * <p>
- * The particular persistence layer implementation in use needs to be configured,
- * with a BeanManager, that is able to resolve injection points for this EntityListener.
- *
- * @since 2.0 {@index}
+ * Use {@link IsisEntityListener} instead.
  */
+@Deprecated
 @Log4j2
-public class JpaEntityInjectionPointResolver {
-
-    @Inject // not managed by Spring (directly)
-    private ServiceInjector serviceInjector;
-
-    @PrePersist
-    @PreUpdate
-    @PreRemove
-    private void beforeAnyUpdate(Object entityPojo) {
-        log.debug("beforeAnyUpdate: {}", entityPojo);
-        serviceInjector.injectServicesInto(entityPojo);
-    }
-
-    @PostPersist
-    @PostUpdate
-    @PostRemove
-    private void afterAnyUpdate(Object entityPojo) {
-        log.debug("afterAnyUpdate: {}", entityPojo);
-    }
-
-    @PostLoad
-    private void afterLoad(Object entityPojo) {
-        log.debug("afterLoad: {}", entityPojo);
-        serviceInjector.injectServicesInto(entityPojo);
-    }
+public class JpaEntityInjectionPointResolver extends IsisEntityListener {
 
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
index 1b0d317..ca75643 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/InteractionBoundaryProbe.java
@@ -24,8 +24,10 @@ import javax.inject.Inject;
 
 import org.junit.jupiter.api.Assertions;
 import org.springframework.context.event.EventListener;
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.core.interaction.scope.InteractionScopeAware;
 import org.apache.isis.core.transaction.events.TransactionAfterCompletionEvent;
@@ -56,14 +58,14 @@ public class InteractionBoundaryProbe implements InteractionScopeAware {
     }
 
     /** TRANSACTION BEGIN BOUNDARY */
-    @EventListener(TransactionBeforeCompletionEvent.class)
+    @EventListener(TransactionBeforeCompletionEvent.class) @Order(PriorityPrecedence.FIRST + 100)
     public void onTransactionEnding(TransactionBeforeCompletionEvent event) {
         log.debug("txStarted");
         kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txEnding");
     }
 
     /** TRANSACTION END BOUNDARY */
-    @EventListener(TransactionAfterCompletionEvent.class)
+    @EventListener(TransactionAfterCompletionEvent.class) @Order(PriorityPrecedence.LAST - 100)
     public void onTransactionEnded(TransactionAfterCompletionEvent event) {
         if(event.isRolledBack()) {
             kvStoreForTesting.incrementCounter(InteractionBoundaryProbe.class, "txRolledBack");