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 ee99e8f73b ISIS-3265: fail early on nested getPojo() call
ee99e8f73b is described below

commit ee99e8f73b9711626add8deb9c6a9518963836ed
Author: Andi Huber <[email protected]>
AuthorDate: Thu Oct 27 14:01:42 2022 +0200

    ISIS-3265: fail early on nested getPojo() call
---
 .../causeway/applib/events/EventObjectBase.java    |  4 +--
 .../object/_ManagedObjectEntityBookmarked.java     | 40 ++++++++++++++++------
 2 files changed, 31 insertions(+), 13 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/events/EventObjectBase.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/events/EventObjectBase.java
index 407a014c42..4c3bee3b00 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/events/EventObjectBase.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/events/EventObjectBase.java
@@ -43,7 +43,7 @@ public abstract class EventObjectBase<T> {
      * Initializes the event's source with given {@code source}.
      */
     public static <T, E extends EventObjectBase<T>> Optional<E> 
getInstanceWithSource(
-            final Class<E> eventType, final T source) {
+            final Class<E> eventType, final @Nullable T source) {
         return getInstanceWithSourceSupplier(eventType, (Supplier<T>) 
()->source);
     }
 
@@ -54,7 +54,7 @@ public abstract class EventObjectBase<T> {
      * Initializes the event's source lazily, that is using given {@code 
eventSourceSupplier}.
      */
     public static <T, E extends EventObjectBase<T>> Optional<E> 
getInstanceWithSourceSupplier(
-            final Class<E> eventType, final Supplier<T> eventSourceSupplier) {
+            final Class<E> eventType, final @Nullable Supplier<T> 
eventSourceSupplier) {
         return _Reflect.getPublicConstructors(eventType)
             .filter(paramCount(0))
             .getFirst()
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/_ManagedObjectEntityBookmarked.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/_ManagedObjectEntityBookmarked.java
index 6f4993b60c..888c4b06bd 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/_ManagedObjectEntityBookmarked.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/_ManagedObjectEntityBookmarked.java
@@ -89,8 +89,34 @@ implements _Refetchable {
             return pojo; // is attached
         }
 
-        //FIXME[ISIS-3265] this getPojo() call might originate from a 
CausewayEntityListener.onPostLoad event,
-        // in which case we get into a loop that results in a stack overflow
+        //[ISIS-3265] this getPojo() call might originate from a 
CausewayEntityListener.onPostLoad event,
+        // in which case potentially runs into a nested loop resulting in a 
stack overflow;
+        if(refetching) {
+            throw _Exceptions.unrecoverable("framework bug: nested call to 
getPojo() while already refetching");
+        }
+
+        refetching = true;
+        val refetchedPojo = refetchPojo(entityState);
+        refetching = false;
+
+        return this.pojo = assertCompliance(refetchedPojo);
+    }
+
+    @Override
+    public @NonNull EntityState getEntityState() {
+        val entityFacet = entityFacet();
+        return entityFacet.getEntityState(pojo);
+    }
+
+    // -- HELPER
+
+    private boolean refetching;
+
+    private Object refetchPojo(final EntityState entityState) {
+
+        val entityFacet = entityFacet();
+
+        // triggers live-cycle events
         val refetchedIfSuccess = entityFacet.fetchByBookmark(bookmark);
 
         if(refetchedIfSuccess.isEmpty()) {
@@ -111,17 +137,9 @@ implements _Refetchable {
 
         _XrayEvent.event("Entity %s refetched from persistence.", 
getSpecification());
 
-        return this.pojo = assertCompliance(refetchedPojo);
+        return refetchedPojo;
     }
 
-    @Override
-    public @NonNull EntityState getEntityState() {
-        val entityFacet = entityFacet();
-        return entityFacet.getEntityState(pojo);
-    }
-
-    // -- HELPER
-
     private EntityFacet entityFacet() {
         return getSpecification().entityFacetElseFail();
     }

Reply via email to