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 2021/12/08 20:32:50 UTC

[isis] branch master updated: ISIS-2911: further refactors ViewModelFacet

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 bcdeaae  ISIS-2911: further refactors ViewModelFacet
bcdeaae is described below

commit bcdeaae4c1e96c8866e5613d0e20b9c2288e3452
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Dec 8 21:31:23 2021 +0100

    ISIS-2911: further refactors ViewModelFacet
    
    - use Bookmark instead of String to represent a memento
---
 .../appfeatui/ApplicationFeatureViewModel.java       | 16 +++++++++++-----
 .../isis/applib/services/factory/FactoryService.java |  5 +++--
 .../_testing/FactoryService_forTesting.java          |  3 ++-
 .../recreatable/RecreatableObjectFacetAbstract.java  | 15 ++++++++-------
 ...leObjectFacetDeclarativeInitializingAbstract.java |  5 +++--
 ...jectFacetForRecreatableDomainObjectInterface.java |  5 +++--
 ...ableObjectFacetForRecreatableObjectInterface.java |  5 +++--
 ...atableObjectFacetForXmlRootElementAnnotation.java |  7 ++++---
 .../facets/object/viewmodel/ViewModelFacet.java      | 20 +++++++++++---------
 .../load/ObjectLoader_builtinHandlers.java           |  4 ++--
 .../factory/FactoryServiceDefault.java               |  7 ++++---
 .../dom/mixins/perms/UserPermissionViewModel.java    |  5 ++++-
 12 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/appfeatui/ApplicationFeatureViewModel.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeatui/ApplicationFeatureViewModel.java
index 4d64c3a..40aeac2 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/appfeatui/ApplicationFeatureViewModel.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeatui/ApplicationFeatureViewModel.java
@@ -39,12 +39,12 @@ import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.annotation.PropertyLayout;
-import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.appfeat.ApplicationFeature;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.util.Equality;
 import org.apache.isis.applib.util.Hashing;
@@ -84,8 +84,12 @@ public abstract class ApplicationFeatureViewModel implements ViewModel {
             final ApplicationFeatureId featureId,
             final ApplicationFeatureRepository applicationFeatureRepository,
             final FactoryService factoryService) {
-        final Class<? extends ApplicationFeatureViewModel> cls = viewModelClassFor(featureId, applicationFeatureRepository);
-        return factoryService.viewModel(cls, featureId.asEncodedString());
+        final Class<? extends ApplicationFeatureViewModel> cls =
+                viewModelClassFor(featureId, applicationFeatureRepository);
+        return factoryService.viewModel(cls,
+                Bookmark.forLogicalTypeNameAndIdentifier(
+                        featureId.getLogicalTypeName(),
+                        featureId.asEncodedString()));
     }
 
     private static Class<? extends ApplicationFeatureViewModel> viewModelClassFor(
@@ -331,11 +335,13 @@ public abstract class ApplicationFeatureViewModel implements ViewModel {
         }
         final Class<? extends ApplicationFeatureViewModel> cls =
                 viewModelClassFor(parentId, featureRepository);
-        return factory.viewModel(cls, parentId.asEncodedString());
+        return factory.viewModel(cls,
+                Bookmark.forLogicalTypeNameAndIdentifier(
+                        parentId.getLogicalTypeName(),
+                        parentId.asEncodedString()));
     }
 
 
-
     // -- parentPackage (property, programmatic, for packages & classes only)
 
     /**
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java b/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
index 51a7c9c..9dc4976 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/factory/FactoryService.java
@@ -23,6 +23,7 @@ import java.util.NoSuchElementException;
 import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.exceptions.UnrecoverableException;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 
 import lombok.NonNull;
 
@@ -127,7 +128,7 @@ public interface FactoryService {
      * @apiNote forces the viewModelClass to be added to the meta-model if not already
      * @since 2.0
      */
-    <T> T viewModel(@NonNull Class<T> viewModelClass, @Nullable String mementoStr);
+    <T> T viewModel(@NonNull Class<T> viewModelClass, @Nullable Bookmark bookmark);
 
     /**
      * Creates a new ViewModel instance,
@@ -139,7 +140,7 @@ public interface FactoryService {
      * @since 2.0
      */
     default <T> T viewModel(@NonNull final Class<T> viewModelClass) {
-        return viewModel(viewModelClass, /*mementoStr*/null);
+        return viewModel(viewModelClass, /*bookmark*/null);
     }
 
     /**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/FactoryService_forTesting.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/FactoryService_forTesting.java
index aff5f5c..6b56d10 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/FactoryService_forTesting.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/FactoryService_forTesting.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.metamodel._testing;
 
 import org.springframework.lang.Nullable;
 
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 
@@ -62,7 +63,7 @@ class FactoryService_forTesting implements FactoryService {
     }
 
     @Override
-    public <T> T viewModel(final Class<T> viewModelClass, @Nullable final String mementoStr) {
+    public <T> T viewModel(final Class<T> viewModelClass, @Nullable final Bookmark bookmark) {
         throw new IllegalArgumentException("Not yet supported");
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
index ac3ff8e..fabc2d0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
@@ -71,14 +71,15 @@ implements ViewModelFacet {
     }
 
     @Override
-    public final Object instantiate(final Class<?> viewModelClass, final String mementoStr) {
+    public final Object instantiate(final Class<?> viewModelClass, final Bookmark bookmark) {
         if (getRecreationMechanism() == RecreationMechanism.INITIALIZES) {
             throw new IllegalStateException("This view model instantiates rather than initializes");
         }
 
-        val viewModelPojo = _Strings.isNullOrEmpty(mementoStr)
+        val viewModelPojo = bookmark==null
+                    || _Strings.isNullOrEmpty(bookmark.getIdentifier())
                 ? ClassExtensions.newInstance(viewModelClass)
-                : doInstantiate(viewModelClass, mementoStr);
+                : doInstantiate(viewModelClass, bookmark);
 
         getServiceInjector().injectServicesInto(viewModelPojo);
         invokePostConstructMethod(viewModelPojo);
@@ -90,16 +91,16 @@ implements ViewModelFacet {
      * {@link org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet.RecreationMechanism#INSTANTIATES}
      * (ignored otherwise).
      */
-    protected Object doInstantiate(final Class<?> viewModelClass, final String mementoStr) {
+    protected Object doInstantiate(final Class<?> viewModelClass, final Bookmark bookmark) {
         throw new IllegalStateException("doInstantiate() must be overridden if RecreationMechanism is INSTANTIATES");
     }
 
     @Override
-    public final void initialize(final Object viewModelPojo, final String mementoStr) {
+    public final void initialize(final Object viewModelPojo, final Bookmark bookmark) {
         if (getRecreationMechanism() == RecreationMechanism.INSTANTIATES) {
             throw new IllegalStateException("This view model instantiates rather than initializes");
         }
-        doInitialize(viewModelPojo, mementoStr);
+        doInitialize(viewModelPojo, bookmark);
         getServiceInjector().injectServicesInto(viewModelPojo);
         invokePostConstructMethod(viewModelPojo);
     }
@@ -109,7 +110,7 @@ implements ViewModelFacet {
      * {@link org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet.RecreationMechanism#INITIALIZES}
      * (ignored otherwise).
      */
-    protected void doInitialize(final Object viewModelPojo, final String mementoStr) {
+    protected void doInitialize(final Object viewModelPojo, final Bookmark bookmark) {
         throw new IllegalStateException("doInitialize() must be overridden if RecreationMechanism is INITIALIZE");
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
index 83dd80d..5042f1b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.core.metamodel.facets.object.recreatable;
 
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
 import org.apache.isis.commons.internal.memento._Mementos;
 import org.apache.isis.commons.internal.memento._Mementos.SerializingAdapter;
@@ -49,9 +50,9 @@ extends RecreatableObjectFacetAbstract {
     @Override
     protected void doInitialize(
             final Object viewModelPojo,
-            final String mementoStr) {
+            final Bookmark bookmark) {
 
-        val memento = parseMemento(mementoStr);
+        val memento = parseMemento(bookmark.getIdentifier());
         val mementoKeys = memento.keySet();
 
         if(mementoKeys.isEmpty()) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
index 3c059c6..daf08b1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableDomainObjectInterface.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.recreatable;
 
 import org.apache.isis.applib.RecreatableDomainObject;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.HasPostConstructMethodCache;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
@@ -33,9 +34,9 @@ extends RecreatableObjectFacetAbstract {
     }
 
     @Override
-    protected void doInitialize(final Object pojo, final String memento) {
+    protected void doInitialize(final Object pojo, final Bookmark bookmark) {
         final RecreatableDomainObject viewModel = (RecreatableDomainObject)pojo;
-        viewModel.__isis_recreate(memento);
+        viewModel.__isis_recreate(bookmark.getIdentifier());
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
index 339ebc8..8a0b7f3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForRecreatableObjectInterface.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.recreatable;
 
 import org.apache.isis.applib.ViewModel;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.HasPostConstructMethodCache;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
@@ -33,9 +34,9 @@ extends RecreatableObjectFacetAbstract {
     }
 
     @Override
-    protected void doInitialize(final Object pojo, final String memento) {
+    protected void doInitialize(final Object pojo, final Bookmark bookmark) {
         final ViewModel viewModel = (ViewModel) pojo;
-        viewModel.viewModelInit(memento);
+        viewModel.viewModelInit(bookmark.getIdentifier());
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
index 05e853c..fe2148c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.metamodel.facets.object.recreatable;
 
 import java.util.UUID;
 
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.jaxb.JaxbService;
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
 import org.apache.isis.commons.internal.debug._Debug;
@@ -41,14 +42,14 @@ extends RecreatableObjectFacetAbstract {
     }
 
     @Override
-    protected Object doInstantiate(final Class<?> viewModelClass, final String mementoStr) {
-        final String xmlStr = getUrlEncodingService().decodeToString(mementoStr);
+    protected Object doInstantiate(final Class<?> viewModelClass, final Bookmark bookmark) {
+        final String xmlStr = getUrlEncodingService().decodeToString(bookmark.getIdentifier());
         final Object viewModelPojo = getJaxbService().fromXml(viewModelClass, xmlStr);
         return viewModelPojo;
     }
 
     @Override
-    public String serialize(final ManagedObject managedObject) {
+    protected String serialize(final ManagedObject managedObject) {
         final String xml = getJaxbService().toXml(managedObject.getPojo());
         final String encoded = getUrlEncodingService().encodeString(xml);
         //FIXME[ISIS-2903] gets called about 4 times per same object, why?
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
index a99ae51..5f68a0b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacet.java
@@ -66,15 +66,15 @@ public interface ViewModelFacet extends Facet {
 
     default Object createViewModelPojo(
             final ObjectSpecification spec,
-            final String mementoStr,
-            final Function<ObjectSpecification, Object> factory) {
+            final Bookmark bookmark,
+            final Function<ObjectSpecification, Object> viewModelPojoFactory) {
 
         final Object viewModelPojo;
         if(getRecreationMechanism().isInitializes()) {
-            viewModelPojo = factory.apply(spec);
-            initialize(viewModelPojo, mementoStr);
+            viewModelPojo = viewModelPojoFactory.apply(spec);
+            initialize(viewModelPojo, bookmark);
         } else {
-            viewModelPojo = instantiate(spec.getCorrespondingClass(), mementoStr);
+            viewModelPojo = instantiate(spec.getCorrespondingClass(), bookmark);
         }
         return viewModelPojo;
     }
@@ -83,7 +83,8 @@ public interface ViewModelFacet extends Facet {
      * Whether this implementation supports the recreation of objects by {@link RecreationMechanism#INSTANTIATES instantiating} (and implicitly also initializing) a new pojo, or by {@link RecreationMechanism#INITIALIZES initializing} a pojo created and passed to it by the framework.
      *
      * <p>
-     *     Determines whether the framework then calls {@link #instantiate(Class, String)} or if it calls {@link #initialize(Object, String)}.
+     *     Determines whether the framework then calls
+     *     {@link #instantiate(Class, Bookmark)} or if it calls {@link #initialize(Object, Bookmark)}.
      * </p>
      */
     RecreationMechanism getRecreationMechanism();
@@ -91,15 +92,16 @@ public interface ViewModelFacet extends Facet {
     /**
      * Will be called if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INITIALIZES}.
      */
-    void initialize(Object viewModelPojo, String viewModelMemento);
+    void initialize(Object viewModelPojo, Bookmark bookmark);
 
     /**
      * Will be called only if {@link #getRecreationMechanism()} is {@link RecreationMechanism#INSTANTIATES}.
      */
-    Object instantiate(final Class<?> viewModelClass, String viewModelMemento);
+    Object instantiate(final Class<?> viewModelClass, Bookmark bookmark);
 
     /**
-     * Obtain a memento of the pojo, which can then be used to reinstantiate (either by {@link #instantiate(Class, String)} or {@link #initialize(Object, String)}) subsequently.
+     * Obtain a memento of the pojo, which can then be used to reinstantiate
+     * (either by {@link #instantiate(Class, Bookmark)} or {@link #initialize(Object, Bookmark)}) subsequently.
      */
     Bookmark serializeToBookmark(ManagedObject managedObject);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
index 5250f9d..c2d3e90 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
@@ -198,9 +198,9 @@ final class ObjectLoader_builtinHandlers {
             final Object viewModelPojo;
             if(viewModelFacet.getRecreationMechanism().isInitializes()) {
                 viewModelPojo = this.instantiateAndInjectServices(spec);
-                viewModelFacet.initialize(viewModelPojo, bookmark.getIdentifier());
+                viewModelFacet.initialize(viewModelPojo, bookmark);
             } else {
-                viewModelPojo = viewModelFacet.instantiate(spec.getCorrespondingClass(), bookmark.getIdentifier());
+                viewModelPojo = viewModelFacet.instantiate(spec.getCorrespondingClass(), bookmark);
             }
 
             return ManagedObject.bookmarked(spec, viewModelPojo, bookmark);
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
index 4ad25ae..4b835a8 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/factory/FactoryServiceDefault.java
@@ -20,15 +20,16 @@ package org.apache.isis.core.runtimeservices.factory;
 
 import java.lang.reflect.InvocationTargetException;
 
-import org.springframework.lang.Nullable;
 import javax.annotation.Priority;
 import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.applib.services.inject.ServiceInjector;
@@ -145,11 +146,11 @@ public class FactoryServiceDefault implements FactoryService {
     }
 
     @Override
-    public <T> T viewModel(final @NonNull Class<T> viewModelClass, final @Nullable String mementoStr) {
+    public <T> T viewModel(final @NonNull Class<T> viewModelClass, final @Nullable Bookmark bookmark) {
 
         val spec = loadSpec(viewModelClass);
         val viewModelFacet = getViewModelFacet(spec);
-        val viewModel = viewModelFacet.createViewModelPojo(spec, mementoStr, __->createObject(spec));
+        val viewModel = viewModelFacet.createViewModelPojo(spec, bookmark, __->createObject(spec));
         return _Casts.uncheckedCast(viewModel);
     }
 
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/perms/UserPermissionViewModel.java b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/perms/UserPermissionViewModel.java
index 166289b..6c6e932 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/perms/UserPermissionViewModel.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/isis/extensions/secman/applib/user/dom/mixins/perms/UserPermissionViewModel.java
@@ -46,6 +46,7 @@ import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureRepository;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureSort;
 import org.apache.isis.applib.services.appfeatui.ApplicationFeatureViewModel;
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ToString;
@@ -100,7 +101,9 @@ public class UserPermissionViewModel implements ViewModel {
         return factory
                 .viewModel(
                         UserPermissionViewModel.class,
-                        asEncodedString(featureId, user.getUsername(), viewingEvaluation, changingEvaluation));
+                        Bookmark.forLogicalTypeNameAndIdentifier(
+                                UserPermissionViewModel.LOGICAL_TYPE_NAME,
+                                asEncodedString(featureId, user.getUsername(), viewingEvaluation, changingEvaluation)));
     }
 
     public UserPermissionViewModel() {