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 2022/06/09 13:40:30 UTC
[isis] branch master updated: ISIS-3008: optimization: refresh viewmodels only once per interaction
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 5db723fc2b ISIS-3008: optimization: refresh viewmodels only once per interaction
5db723fc2b is described below
commit 5db723fc2be4acce886c62295f1e4d17c84b8fdf
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Jun 9 15:40:24 2022 +0200
ISIS-3008: optimization: refresh viewmodels only once per interaction
---
.../isis/core/metamodel/spec/ManagedObject.java | 134 ++++++++++++++-------
.../isis/core/metamodel/spec/ManagedObjects.java | 44 ++-----
.../core/metamodel/spec/PackedManagedObject.java | 20 ++-
.../components/scalars/ScalarPanelAbstract2.java | 4 +-
4 files changed, 109 insertions(+), 93 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
index 87ef6931cf..980ab25032 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
@@ -18,7 +18,9 @@
*/
package org.apache.isis.core.metamodel.spec;
+import java.util.Objects;
import java.util.Optional;
+import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
@@ -35,6 +37,7 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facets.object.icon.ObjectIcon;
import org.apache.isis.core.metamodel.facets.object.title.TitleRenderRequest;
+import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
@@ -65,15 +68,6 @@ public interface ManagedObject {
*/
Object getPojo();
- /**
- * Introduced, so we can re-fetch detached entity pojos in place.
- * @apiNote should be package private, and not publicly exposed
- * (but the <i>Java</i> language is not there yet)
- */
- void replacePojo(UnaryOperator<Object> replacer);
-
- void replaceBookmark(UnaryOperator<Bookmark> replacer);
-
/**
* Returns the object's bookmark as identified by the ObjectManager.
* Bookmarks are considered immutable, hence will be memoized once fetched.
@@ -91,39 +85,11 @@ public interface ManagedObject {
Optional<Bookmark> getBookmarkRefreshed();
/**
- * Reload current viewmodel object from memoized bookmark, otherwise does nothing.
+ * If the underlying domain object is a viewmodel, refreshes any referenced entities.
+ * (Acts as a no-op otherwise.)
+ * @apiNote usually should be sufficient to refresh once per interaction.
*/
- default void reloadViewmodelFromMemoizedBookmark() {
- val spec = getSpecification();
- if(isBookmarkMemoized()
- && spec.isViewModel()) {
-
- val bookmark = getBookmark().get();
- val viewModelClass = spec.getCorrespondingClass();
-
- val recreatedViewmodel =
- getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
-
- _XrayEvent.event("Viewmodel '%s' recreated from memoized bookmark.", viewModelClass.getName());
-
- replacePojo(old->recreatedViewmodel);
- }
- }
-
- default void reloadViewmodelFromBookmark(final @NonNull Bookmark bookmark) {
- val spec = getSpecification();
- if(spec.isViewModel()) {
- val viewModelClass = spec.getCorrespondingClass();
-
- val recreatedViewmodel =
- getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
-
- _XrayEvent.event("Viewmodel '%s' recreated from provided bookmark.", viewModelClass.getName());
-
- replacePojo(old->recreatedViewmodel);
- replaceBookmark(old->bookmark);
- }
- }
+ void refreshViewmodel(@Nullable Supplier<Bookmark> bookmarkSupplier);
boolean isBookmarkMemoized();
@@ -341,8 +307,7 @@ public interface ManagedObject {
return getBookmark();
}
- @Override
- public final void replaceBookmark(final UnaryOperator<Bookmark> replacer) {
+ private void replaceBookmark(final UnaryOperator<Bookmark> replacer) {
final Bookmark old = bookmarkLazy.isMemoized()
? bookmarkLazy.get().orElse(null)
: null;
@@ -367,6 +332,89 @@ public interface ManagedObject {
.map(objectManager->objectManager.bookmarkObject(adapter));
}
+ // -- REFRESH OPTIMIZATION
+
+ private UUID interactionId = null;
+
+ @Override
+ public final void refreshViewmodel(final @Nullable Supplier<Bookmark> bookmarkSupplier) {
+ val spec = getSpecification();
+ if(spec.isViewModel()) {
+ val viewModelFacet = spec.getFacet(ViewModelFacet.class);
+ if(viewModelFacet.containsEntities()) {
+
+ val shouldRefresh = spec.getMetaModelContext().getInteractionProvider().getInteractionId()
+ .map(this::shouldRefresh)
+ .orElse(true); // if there is no current interaction, refresh regardless; unexpected state, might fail later
+
+ if(!shouldRefresh) {
+ return;
+ }
+
+ if(isBookmarkMemoized()) {
+ reloadViewmodelFromMemoizedBookmark();
+ } else {
+ val bookmark = bookmarkSupplier!=null
+ ? bookmarkSupplier.get()
+ : null;
+ if(bookmark!=null) {
+ reloadViewmodelFromBookmark(bookmark);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean shouldRefresh(final @NonNull UUID interactionId) {
+ if(Objects.equals(this.interactionId, interactionId)) {
+ return false; // already refreshed within current interaction
+ }
+ this.interactionId = interactionId;
+ return true;
+ }
+
+ /**
+ * Reload current viewmodel object from memoized bookmark, otherwise does nothing.
+ */
+ private void reloadViewmodelFromMemoizedBookmark() {
+ val spec = getSpecification();
+ if(isBookmarkMemoized()
+ && spec.isViewModel()) {
+
+ val bookmark = getBookmark().get();
+ val viewModelClass = spec.getCorrespondingClass();
+
+ val recreatedViewmodel =
+ getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
+
+ _XrayEvent.event("Viewmodel '%s' recreated from memoized bookmark.", viewModelClass.getName());
+
+ replacePojo(old->recreatedViewmodel);
+ }
+ }
+
+ private void reloadViewmodelFromBookmark(final @NonNull Bookmark bookmark) {
+ val spec = getSpecification();
+ if(spec.isViewModel()) {
+ val viewModelClass = spec.getCorrespondingClass();
+
+ val recreatedViewmodel =
+ getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
+
+ _XrayEvent.event("Viewmodel '%s' recreated from provided bookmark.", viewModelClass.getName());
+
+ replacePojo(old->recreatedViewmodel);
+ replaceBookmark(old->bookmark);
+ }
+ }
+
+ /**
+ * Introduced, so we can re-fetch detached entity pojos in place.
+ * @apiNote should be package private, and not publicly exposed
+ * (but the <i>Java</i> language is not there yet)
+ */
+ abstract void replacePojo(UnaryOperator<Object> replacer);
+
}
// -- SIMPLE
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
index 74330e565c..9a9da66d0f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
@@ -44,13 +44,12 @@ import org.apache.isis.applib.services.repository.EntityState;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.functional.Try;
import org.apache.isis.commons.internal.assertions._Assert;
+import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.base._Objects;
import org.apache.isis.commons.internal.collections._Arrays;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Sets;
-import org.apache.isis.commons.internal.debug._Debug;
-import org.apache.isis.commons.internal.debug.xray.XrayUi;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.config.beans.PersistenceStack;
import org.apache.isis.core.metamodel.commons.CanonicalInvoker;
@@ -59,12 +58,12 @@ import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.facets.collections.CollectionFacet;
import org.apache.isis.core.metamodel.facets.object.entity.EntityFacet;
import org.apache.isis.core.metamodel.facets.object.title.TitleRenderRequest;
-import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.interactions.InteractionHead;
import org.apache.isis.core.metamodel.interactions.InteractionUtils;
import org.apache.isis.core.metamodel.interactions.ObjectVisibilityContext;
import org.apache.isis.core.metamodel.interactions.VisibilityContext;
import org.apache.isis.core.metamodel.objectmanager.load.ObjectLoader;
+import org.apache.isis.core.metamodel.spec.ManagedObject.ManagedObjectWithBookmark;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import lombok.NonNull;
@@ -510,15 +509,8 @@ public final class ManagedObjects {
}
@Override
- public void replacePojo(final UnaryOperator<Object> replacer) {
- }
-
- @Override
- public void replaceBookmark(final UnaryOperator<Bookmark> replacer) {
- }
-
- @Override
- public void reloadViewmodelFromMemoizedBookmark() {
+ public void refreshViewmodel(final @Nullable Supplier<Bookmark> bookmarkSupplier) {
+ // noop; only available for viewmodels
}
};
@@ -727,7 +719,9 @@ public final class ManagedObjects {
val newState = EntityUtil.getEntityState(reattached);
_Assert.assertTrue(newState.isAttached());
- managedObject.replacePojo(old->reattached.getPojo());
+ _Casts.castTo(ManagedObjectWithBookmark.class, managedObject)
+ .ifPresent(obj->obj.replacePojo(old->reattached.getPojo()));
+
return managedObject;
}
@@ -1136,29 +1130,7 @@ public final class ManagedObjects {
if(isNullOrUnspecifiedOrEmpty(viewmodel)) {
return; // do nothing
}
-
- val spec = viewmodel.getSpecification();
- if(spec.isViewModel()) {
- val viewModelFacet = spec.getFacet(ViewModelFacet.class);
- if(viewModelFacet.containsEntities()) {
-
- _Debug.onCondition(XrayUi.isXrayEnabled(), ()->{
- _Debug.log("about to refresh viewmodel ..");
- });
-
- if(viewmodel.isBookmarkMemoized()) {
- viewmodel.reloadViewmodelFromMemoizedBookmark();
- } else {
- val bookmark = bookmarkSupplier!=null
- ? bookmarkSupplier.get()
- : null;
- if(bookmark!=null) {
- viewmodel.reloadViewmodelFromBookmark(bookmark);
- }
- }
- }
- }
+ viewmodel.refreshViewmodel(bookmarkSupplier);
}
-
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/PackedManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/PackedManagedObject.java
index 2377970dcb..a64ad4baf7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/PackedManagedObject.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/PackedManagedObject.java
@@ -20,13 +20,14 @@ package org.apache.isis.core.metamodel.spec;
import java.util.Collections;
import java.util.Optional;
-import java.util.function.UnaryOperator;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
+import org.springframework.lang.Nullable;
+
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Lazy;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
import lombok.RequiredArgsConstructor;
@@ -55,16 +56,6 @@ public final class PackedManagedObject implements ManagedObject {
.collect(Collectors.toList()));
}
- @Override
- public void replacePojo(final UnaryOperator<Object> replacer) {
- throw _Exceptions.unsupportedOperation();
- }
-
- @Override
- public void replaceBookmark(final UnaryOperator<Bookmark> replacer) {
- throw _Exceptions.unsupportedOperation();
- }
-
private final _Lazy<Optional<Bookmark>> bookmarkLazy =
_Lazy.threadSafe(()->{
return Optional.of(getSpecification().getMetaModelContext().getObjectManager().bookmarkObject(this));
@@ -89,4 +80,9 @@ public final class PackedManagedObject implements ManagedObject {
return nonScalar;
}
+ @Override
+ public void refreshViewmodel(final @Nullable Supplier<Bookmark> bookmarkSupplier) {
+ // noop; only available for viewmodels
+ }
+
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
index f177cc1e3e..0643f66943 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
@@ -214,8 +214,8 @@ extends ScalarPanelAbstract {
// add clear-field-button (only if feature is not required and not already cleared)
val isClearFieldButtonVisible =
- scalarModel().proposedValue().isPresent()
- && !scalarModel().isRequired();
+ !scalarModel().isRequired()
+ && scalarModel().proposedValue().isPresent();
if(isClearFieldButtonVisible) {
val clearFieldButton = Wkt.linkAddWithBody(buttonContainer,