Repository: isis Updated Branches: refs/heads/master 4dd4a435e -> e7d7ab5f3
ISIS-1435: fixes infinite recursion for updating() ... as demonstrated by public void updating() { setName(getName() + " - updating"; } We now only call the updating() callback, and also the domain event lifecycle callback, if it hasn't previously been called. We figure that out by looking asking the ChangedObjectsService (new API) as to whether the object was previously changed or not (if so, then don't fire the callbacks). Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/e7d7ab5f Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/e7d7ab5f Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/e7d7ab5f Branch: refs/heads/master Commit: e7d7ab5f3a578f7c5434e2694c2fad8f2f97a2e0 Parents: 4dd4a43 Author: Dan Haywood <d...@haywood-associates.co.uk> Authored: Thu Jun 23 18:42:03 2016 +0100 Committer: Dan Haywood <d...@haywood-associates.co.uk> Committed: Thu Jun 23 18:42:03 2016 +0100 ---------------------------------------------------------------------- .../changes/ChangedObjectsServiceInternal.java | 24 +++++++++----------- .../system/persistence/PersistenceSession.java | 11 +++++++-- 2 files changed, 20 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/e7d7ab5f/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java index 9aa6d63..ffd5721 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/changes/ChangedObjectsServiceInternal.java @@ -24,7 +24,6 @@ import java.util.Set; import javax.enterprise.context.RequestScoped; -import com.google.common.base.Predicate; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -33,11 +32,12 @@ import org.apache.isis.applib.annotation.NatureOfService; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.annotation.PublishedObject; import org.apache.isis.applib.services.HasTransactionId; +import org.apache.isis.applib.services.WithTransactionScope; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; +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.system.transaction.IsisTransaction; -import org.apache.isis.applib.services.WithTransactionScope; @DomainService(nature = NatureOfService.DOMAIN) @RequestScoped @@ -66,6 +66,12 @@ public class ChangedObjectsServiceInternal implements WithTransactionScope { // used for publishing private final Map<ObjectAdapter,PublishedObject.ChangeKind> changeKindByEnlistedAdapter = Maps.newLinkedHashMap(); + @Programmatic + public boolean isEnlisted(ObjectAdapter adapter) { + return changeKindByEnlistedAdapter.containsKey(adapter); + } + + /** * Auditing and publishing support: for object stores to enlist an object that has just been created, * capturing a dummy value <tt>'[NEW]'</tt> for the pre-modification value. @@ -172,9 +178,6 @@ public class ChangedObjectsServiceInternal implements WithTransactionScope { /** - * - * @param adapter - * @param current * @return <code>true</code> if successfully enlisted, <code>false</code> if was already enlisted */ private boolean enlistForPublishing(final ObjectAdapter adapter, final PublishedObject.ChangeKind current) { @@ -247,15 +250,10 @@ public class ChangedObjectsServiceInternal implements WithTransactionScope { Sets.filter(processedObjectProperties1.entrySet(), PreAndPostValues.Predicates.CHANGED)); } - private static final Predicate<ObjectAdapter> IS_TRANSACTION_ID = new Predicate<ObjectAdapter>() { - @Override - public boolean apply(ObjectAdapter input) { - return HasTransactionId.class.isAssignableFrom(input.getSpecification().getCorrespondingClass()); - } - }; - protected boolean shouldIgnore(final ObjectAdapter adapter) { - return IS_TRANSACTION_ID.apply(adapter); + final ObjectSpecification adapterSpec = adapter.getSpecification(); + final Class<?> adapterClass = adapterSpec.getCorrespondingClass(); + return HasTransactionId.class.isAssignableFrom(adapterClass); } http://git-wip-us.apache.org/repos/asf/isis/blob/e7d7ab5f/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java ---------------------------------------------------------------------- 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 9d47b80..1f21a5c 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 @@ -2283,11 +2283,18 @@ public class PersistenceSession implements return; } - CallbackFacet.Util.callCallback(adapter, UpdatingCallbackFacet.class); - postLifecycleEventIfRequired(adapter, UpdatingLifecycleEventFacet.class); + final boolean wasAlreadyEnlisted = changedObjectsServiceInternal.isEnlisted(adapter); + // we call this come what may; + // additional properties may now have been changed, and the changeKind for publishing might also be modified changedObjectsServiceInternal.enlistUpdating(adapter); + 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); + } + ensureRootObject(pojo); }