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/09 15:06:47 UTC

[isis] branch master updated: ISIS-2911: various fixes around recent introduction of PackedManagedObject

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 e862add  ISIS-2911: various fixes around recent introduction of PackedManagedObject
e862add is described below

commit e862add22a6bb7a6b866e316851bf95ce9b4b661
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Dec 9 16:06:35 2021 +0100

    ISIS-2911: various fixes around recent introduction of
    PackedManagedObject
    
    - when an ManagedObject represents a non-scalar it must be wrapped with
    a PackedManagedObject
---
 .../facets/collections/CollectionFacet.java        |  7 ++++
 .../interactions/managed/ManagedAction.java        | 10 ++----
 .../managed/nonscalar/DataTableModel.java          | 19 +++++-----
 .../metamodel/objectmanager/ObjectManager.java     | 10 +++++-
 .../identify/ObjectBookmarker_builtinHandlers.java |  2 ++
 .../load/ObjectLoader_builtinHandlers.java         |  2 +-
 .../memento/ObjectMementoService.java              |  2 ++
 .../isis/core/metamodel/spec/ManagedObject.java    | 25 +++++++++----
 .../core/metamodel/spec/PackedManagedObject.java   | 12 +++++--
 .../TitleAnnotationFacetFactoryTest.java           | 17 ++++++---
 .../executor/MemberExecutorServiceDefault.java     | 42 ++++++++++++----------
 .../memento/ObjectMementoServiceDefault.java       | 41 +++++++--------------
 .../testdomain/interact/CommandArgumentTest.java   |  6 ++--
 .../models/EntityCollectionModelStandalone.java    |  3 +-
 .../wicket/model/models/ManagedObjectModel.java    |  5 +--
 .../actionresponse/ActionResultResponseType.java   | 23 +++++++-----
 16 files changed, 129 insertions(+), 97 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacet.java
index b55a607..0610a1a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacet.java
@@ -49,6 +49,7 @@ import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects.UnwrapUtil;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 
 import lombok.NonNull;
 import lombok.val;
@@ -111,12 +112,18 @@ public interface CollectionFacet extends Facet {
     }
 
     public static int elementCount(@Nullable final ManagedObject container) {
+        if(container instanceof PackedManagedObject) {
+            return ((PackedManagedObject)container).unpack().size();
+        }
         return lookup(container)
                 .map(collectionFacet->collectionFacet.size(container))
                 .orElse(0);
     }
 
     public static Stream<ManagedObject> streamAdapters(@Nullable final ManagedObject container) {
+        if(container instanceof PackedManagedObject) {
+            return ((PackedManagedObject)container).unpack().stream();
+        }
         return lookup(container)
                 .map(collectionFacet->collectionFacet.stream(container))
                 .orElse(Stream.empty());
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
index b62018c..142b07a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
@@ -186,12 +186,13 @@ public final class ManagedAction extends ManagedMember {
         }
 
         val resultPojo = actionResult.getPojo();
+        val objManager = mmc().getObjectManager();
 
         val resultAdapter = getRoutingServices().stream()
                 .filter(routingService->routingService.canRoute(resultPojo))
                 .map(routingService->routingService.route(resultPojo))
                 .filter(_NullSafe::isPresent)
-                .map(this::toManagedObject)
+                .map(objManager::adapt)
                 .filter(_NullSafe::isPresent)
                 .findFirst()
                 .orElse(actionResult);
@@ -201,13 +202,6 @@ public final class ManagedAction extends ManagedMember {
         return resultAdapter;
     }
 
-
-    // -- POJO WRAPPING
-
-    private ManagedObject toManagedObject(final Object pojo) {
-        return ManagedObject.lazy(mmc().getSpecificationLoader(), pojo);
-    }
-
     // -- ACTION RESULT ROUTING
 
     private Can<RoutingService> getRoutingServices() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/nonscalar/DataTableModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/nonscalar/DataTableModel.java
index 6fca658..d937ef5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/nonscalar/DataTableModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/nonscalar/DataTableModel.java
@@ -27,11 +27,11 @@ import org.springframework.lang.Nullable;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.binding._BindableAbstract;
 import org.apache.isis.commons.internal.binding._Bindables;
 import org.apache.isis.commons.internal.binding._Observables;
 import org.apache.isis.commons.internal.binding._Observables.LazyObservable;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.interactions.InteractionHead;
@@ -47,7 +47,7 @@ import org.apache.isis.core.metamodel.interactions.managed.ManagedMember;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedMember.MemberType;
 import org.apache.isis.core.metamodel.interactions.managed.MultiselectChoices;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ManagedObjects;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
 import lombok.AccessLevel;
@@ -74,13 +74,14 @@ implements MultiselectChoices {
             final Can<ManagedObject> args,
             final ManagedObject actionResult) {
 
-        val objectManager = managedAction.getMetaModel().getMetaModelContext().getObjectManager();
-        return new DataTableModel(managedAction, managedAction.getWhere(), ()->
-            ManagedObjects.isNullOrUnspecifiedOrEmpty(actionResult)
-                ? Can.empty()
-                : _NullSafe.streamAutodetect(actionResult.getPojo())
-                        .map(objectManager::adapt)
-                        .collect(Can.toCan()));
+        if(actionResult==null) {
+            new DataTableModel(managedAction, managedAction.getWhere(), Can::empty);
+        }
+        if(!(actionResult instanceof PackedManagedObject)) {
+            throw _Exceptions.unexpectedCodeReach();
+        }
+        return new DataTableModel(managedAction, managedAction.getWhere(),
+                ()->((PackedManagedObject)actionResult).unpack());
     }
 
     // -- CONSTRUCTION
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/ObjectManager.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/ObjectManager.java
index 11baa66..1fbfbf8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/ObjectManager.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/ObjectManager.java
@@ -24,6 +24,7 @@ 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._NullSafe;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.objectmanager.create.ObjectCreator;
 import org.apache.isis.core.metamodel.objectmanager.detach.ObjectDetacher;
@@ -35,6 +36,7 @@ import org.apache.isis.core.metamodel.objectmanager.refresh.ObjectRefresher;
 import org.apache.isis.core.metamodel.objectmanager.serialize.ObjectSerializer;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 
 import lombok.val;
 
@@ -118,7 +120,13 @@ public interface ObjectManager {
         if(spec==null) {
             return ManagedObject.unspecified();
         }
-        return ManagedObject.of(spec, pojo);
+        return spec.isNotCollection()
+                ? ManagedObject.of(spec, pojo)
+                : PackedManagedObject.pack(spec.getElementSpecification().orElse(spec),
+                        _NullSafe.streamAutodetect(pojo)
+                        .map(this::adapt)
+                        .collect(Can.toCan()));
+
     }
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
index 6023819..e9e6257 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
@@ -36,8 +36,10 @@ import org.apache.isis.core.metamodel.facets.object.entity.PersistenceStandard;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.objectmanager.identify.ObjectBookmarker.Handler;
+import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMementoService;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects.EntityUtil;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 
 import lombok.SneakyThrows;
 import lombok.val;
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 c2d3e90..c6db42f 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
@@ -282,7 +282,7 @@ final class ObjectLoader_builtinHandlers {
 
             // unknown object load request
 
-            throw _Exceptions.illegalArgument(
+             throw _Exceptions.illegalArgument(
                     "None of the registered ObjectLoaders knows how to load this object. (loader: %s loading %s)",
                         this.getClass().getName(), objectLoadRequest);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoService.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoService.java
index 8a94448..4390b82 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoService.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoService.java
@@ -33,6 +33,8 @@ public interface ObjectMementoService {
 
     ObjectMemento mementoForObject(ManagedObject adapter);
 
+    //ObjectMemento mementoForObjects(PackedManagedObject adapter);
+
     ObjectMemento mementoForPojo(Object pojo);
 
     ObjectMemento mementoForPojos(Iterable<Object> iterablePojos, LogicalType logicalType);
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 106a719..6dc9514 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
@@ -26,7 +26,9 @@ import java.util.function.UnaryOperator;
 import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._Lazy;
+import org.apache.isis.commons.internal.collections._Collections;
 import org.apache.isis.commons.internal.debug._XrayEvent;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -203,17 +205,14 @@ public interface ManagedObject {
         //actual type in use (during runtime) might be a sub-class of the above
         if(pojo==null
                 || pojo.getClass().equals(specification.getCorrespondingClass())
-                ) {
+                || specification.isValue()) {
             // if actual type matches spec's, we assume, that we don't need to reload,
             // so this is a shortcut for performance reasons
             return SimpleManagedObject.of(specification, pojo);
         }
 
-        //_Probe.errOut("upgrading spec %s on type %s", specification, pojo.getClass());
-        //ManagedObjects.warnIfAttachedEntity(adapter, "consider using ManagedObject.identified(...) for entity");
-
-        val specLoader = specification.getMetaModelContext().getSpecificationLoader();
-        return ManagedObject.lazy(specLoader, pojo);
+        val objManager = specification.getMetaModelContext().getObjectManager();
+        return objManager.adapt(pojo);
     }
 
     /**
@@ -224,6 +223,10 @@ public interface ManagedObject {
             final @NonNull Object pojo,
             final @NonNull Bookmark bookmark) {
 
+        if(pojo!=null) {
+            _Assert.assertFalse(_Collections.isCollectionOrArrayOrCanType(pojo.getClass()));
+        }
+
         if(!specification.getCorrespondingClass().isAssignableFrom(pojo.getClass())) {
             throw _Exceptions.illegalArgument(
                     "Pojo not compatible with ObjectSpecification, " +
@@ -244,6 +247,11 @@ public interface ManagedObject {
     public static ManagedObject lazy(
             final SpecificationLoader specLoader,
             final Object pojo) {
+
+        if(pojo!=null) {
+            _Assert.assertFalse(_Collections.isCollectionOrArrayOrCanType(pojo.getClass()));
+        }
+
         ManagedObjects.assertPojoNotManaged(pojo);
         val adapter = new LazyManagedObject(cls->specLoader.specForType(cls).orElse(null), pojo);
         //ManagedObjects.warnIfAttachedEntity(adapter, "consider using ManagedObject.identified(...) for entity");
@@ -276,6 +284,11 @@ public interface ManagedObject {
                 @NonNull  final ObjectSpecification spec,
                 final @Nullable Object pojo,
                 @NonNull  final Bookmark bookmark) {
+
+            if(pojo!=null) {
+                _Assert.assertFalse(_Collections.isCollectionOrArrayOrCanType(pojo.getClass()));
+            }
+
             val managedObject = SimpleManagedObject.of(spec, pojo);
             managedObject.bookmarkLazy.set(Optional.of(bookmark));
             return managedObject;
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 7fde910..2377970 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
@@ -25,6 +25,7 @@ import java.util.stream.Collectors;
 
 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;
@@ -64,19 +65,24 @@ public final class PackedManagedObject implements ManagedObject {
         throw _Exceptions.unsupportedOperation();
     }
 
+    private final _Lazy<Optional<Bookmark>> bookmarkLazy =
+            _Lazy.threadSafe(()->{
+                return Optional.of(getSpecification().getMetaModelContext().getObjectManager().bookmarkObject(this));
+            });
+
     @Override
     public Optional<Bookmark> getBookmark() {
-        throw _Exceptions.unsupportedOperation();
+        return bookmarkLazy.get();
     }
 
     @Override
     public Optional<Bookmark> getBookmarkRefreshed() {
-        return getBookmark();
+        return getBookmark(); // no-effect
     }
 
     @Override
     public boolean isBookmarkMemoized() {
-        throw _Exceptions.unsupportedOperation();
+        return bookmarkLazy.isMemoized();
     }
 
     public Can<ManagedObject> unpack(){
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
index f5ce06d..0757184 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
@@ -22,7 +22,6 @@ import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
-import java.util.function.Predicate;
 
 import org.jmock.Expectations;
 import org.jmock.auto.Mock;
@@ -31,6 +30,9 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
@@ -43,9 +45,6 @@ import org.apache.isis.core.metamodel.facets.object.title.annotation.TitleFacetV
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
 public class TitleAnnotationFacetFactoryTest
 extends AbstractFacetFactoryJUnit4TestCase {
 
@@ -155,6 +154,9 @@ extends AbstractFacetFactoryJUnit4TestCase {
             allowing(mockStringSpec).getCorrespondingClass();
             will(returnValue(String.class));
 
+            allowing(mockStringSpec).isNotCollection();
+            will(returnValue(true));
+
             allowing(mockStringSpec).isParentedOrFreeCollection();
             will(returnValue(false));
 
@@ -221,7 +223,6 @@ extends AbstractFacetFactoryJUnit4TestCase {
 
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void titleAnnotatedMethodsSomeOfWhichReturnNulls() throws Exception {
 
@@ -247,6 +248,9 @@ extends AbstractFacetFactoryJUnit4TestCase {
                 allowing(mockStringSpec).isParentedOrFreeCollection();
                 will(returnValue(false));
 
+                allowing(mockStringSpec).isNotCollection();
+                will(returnValue(true));
+
                 ignoring(mockStringSpec).assertPojoCompatible(with(any(String.class)));
 
                 allowing(mockSpecificationLoader).specForType(Integer.class);
@@ -258,6 +262,9 @@ extends AbstractFacetFactoryJUnit4TestCase {
                 allowing(mockIntegerSpec).isParentedOrFreeCollection();
                 will(returnValue(false));
 
+                allowing(mockIntegerSpec).isNotCollection();
+                will(returnValue(true));
+
                 allowing(mockIntegerSpec).getTitle(with(any(TitleRenderRequest.class)));
                 will(returnValue("3"));
 
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
index 14ae34c..1eb0163 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
@@ -19,7 +19,6 @@
 package org.apache.isis.core.runtimeservices.executor;
 
 import java.lang.reflect.Method;
-import java.util.Collection;
 import java.util.Optional;
 
 import javax.annotation.Priority;
@@ -63,6 +62,7 @@ import org.apache.isis.core.metamodel.services.publishing.ExecutionPublisher;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.ManagedObjects.UnwrapUtil;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.schema.ixn.v2.ActionInvocationDto;
@@ -304,28 +304,32 @@ implements MemberExecutorService {
             return resultAdapter;
         }
 
-        final Object result = resultAdapter.getPojo();
-
-        if(result instanceof Collection || result.getClass().isArray()) {
-
-            val requiredContainerType = method.getReturnType();
-
-            val autofittedObjectContainer = ManagedObjects.VisibilityUtil
-                    .visiblePojosAutofit(resultAdapter, interactionInitiatedBy, requiredContainerType);
-
-            if (autofittedObjectContainer != null) {
-                return getObjectManager().adapt(autofittedObjectContainer);
-            }
-
-            // would be null if unable to take a copy (unrecognized return type)
-            // fallback to returning the original adapter, without filtering for visibility
-
+        if(resultAdapter instanceof PackedManagedObject) {
             return resultAdapter;
+        }
 
-        } else {
+//        final Object result = resultAdapter.getPojo();
+//
+//        if(result instanceof Collection || result.getClass().isArray()) {
+//
+//            val requiredContainerType = method.getReturnType();
+//
+//            val autofittedObjectContainer = ManagedObjects.VisibilityUtil
+//                    .visiblePojosAutofit(resultAdapter, interactionInitiatedBy, requiredContainerType);
+//
+//            if (autofittedObjectContainer != null) {
+//                return getObjectManager().adapt(autofittedObjectContainer);
+//            }
+//
+//            // would be null if unable to take a copy (unrecognized return type)
+//            // fallback to returning the original adapter, without filtering for visibility
+//
+//            return resultAdapter;
+//
+//        } else {
             boolean visible = ManagedObjects.VisibilityUtil.isVisible(resultAdapter, interactionInitiatedBy);
             return visible ? resultAdapter : null;
-        }
+//        }
     }
 
 
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/ObjectMementoServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/ObjectMementoServiceDefault.java
index 42976b8..3afbb96 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/ObjectMementoServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/ObjectMementoServiceDefault.java
@@ -33,6 +33,7 @@ import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -68,15 +69,13 @@ public class ObjectMementoServiceDefault implements ObjectMementoService {
 
     @Override
     public ObjectMemento mementoForBookmark(@NonNull final Bookmark bookmark) {
-//        _Probe.errOut("mementoForRootOid %s", oid);
         val mementoAdapter = _ObjectMemento.createPersistent(bookmark, specificationLoader);
         return ObjectMementoAdapter.of(mementoAdapter);
     }
 
     @Override
     public ObjectMemento mementoForObject(@Nullable final ManagedObject adapter) {
-        assertSingleton(adapter);
-//        _Probe.errOut("mementoForObject %s", adapter);
+        _Assert.assertFalse(adapter instanceof PackedManagedObject);
         val mementoAdapter = _ObjectMemento.createOrNull(adapter);
         if(mementoAdapter==null) {
             // sonar-ignore-on (fails to detect this as null guard)
@@ -88,10 +87,18 @@ public class ObjectMementoServiceDefault implements ObjectMementoService {
         return ObjectMementoAdapter.of(mementoAdapter);
     }
 
+//    @Override
+//    public ObjectMemento mementoForObjects(@Nullable final PackedManagedObject packedAdapter) {
+//        val listOfMementos = packedAdapter.unpack().stream()
+//                .map(this::mementoForObject)
+//                .collect(Collectors.toCollection(ArrayList::new)); // ArrayList is serializable
+//        return ObjectMementoCollection.of(
+//                listOfMementos,
+//                packedAdapter.getSpecification().getLogicalType());
+//    }
+
     @Override
     public ObjectMemento mementoForParameter(@NonNull final ManagedObject paramAdapter) {
-//        _Probe.errOut("mementoForParameter %s", paramAdapter);
-        assertSingleton(paramAdapter);
         val mementoAdapter = _ObjectMemento.createOrNull(paramAdapter);
         if(mementoAdapter==null) {
             return new ObjectMementoForEmpty(paramAdapter.getSpecification().getLogicalType());
@@ -102,16 +109,12 @@ public class ObjectMementoServiceDefault implements ObjectMementoService {
 
     @Override
     public ObjectMemento mementoForPojo(final Object pojo) {
-        //_Probe.errOut("mementoForPojo %s", ""+pojo);
-        assertSingleton(pojo);
-
         val managedObject = objectManager.adapt(pojo);
         return mementoForObject(managedObject);
     }
 
     @Override
     public ObjectMemento mementoForPojos(final Iterable<Object> iterablePojos, final LogicalType logicalType) {
-//        _Probe.errOut("mementoForPojos");
         val listOfMementos = _NullSafe.stream(iterablePojos)
                 .map(pojo->mementoForPojo(pojo))
                 .collect(Collectors.toCollection(ArrayList::new)); // ArrayList is serializable
@@ -155,26 +158,6 @@ public class ObjectMementoServiceDefault implements ObjectMementoService {
         throw _Exceptions.unrecoverableFormatted("unsupported ObjectMemento type %s", memento.getClass());
     }
 
-//TODO 2x remove if no longer required for debugging ...
-    private void assertSingleton(final ManagedObject adapter) {
-//        if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) {
-//            return;
-//        }
-//        val pojo = ManagedObjects.UnwrapUtil.single(adapter);
-//        assertSingleton(pojo);
-//        val spec = adapter.getSpecification();
-//        if(!spec.isNotCollection()) {
-//            throw _Exceptions.illegalArgument("unexpected spec type %s for %s (elementSpec=%s)",
-//                    spec, spec.getFullIdentifier(), spec.getElementSpecification());
-//        }
-    }
-
-    private void assertSingleton(final Object pojo) {
-//        if(_NullSafe.streamAutodetect(pojo).limit(2).count()>1L) {
-//            throw _Exceptions.illegalArgument("cardinality 0 or 1 expect");
-//        }
-    }
-
     @RequiredArgsConstructor(staticName = "of")
     private static class ObjectMementoAdapter implements ObjectMemento {
 
diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CommandArgumentTest.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CommandArgumentTest.java
index 43340b5..079b495 100644
--- a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CommandArgumentTest.java
+++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/CommandArgumentTest.java
@@ -86,7 +86,7 @@ class CommandArgumentTest extends InteractionTestAbstract {
     public static class CommandArgDemo {
 
         @Action
-        public CommandResult list(List<Long> someIds){
+        public CommandResult list(final List<Long> someIds){
             val stringified = ""+someIds;
             assertEquals("[1, 2, 3]", stringified);
             return CommandResult.of(stringified);
@@ -103,9 +103,7 @@ class CommandArgumentTest extends InteractionTestAbstract {
 
         val pendingArgs = actionInteraction.startParameterNegotiation().get();
 
-        pendingArgs.setParamValue(0, ManagedObject.lazy(
-                objectManager.getMetaModelContext().getSpecificationLoader(),
-                Arrays.asList(1L, 2L, 3L)));
+        pendingArgs.setParamValue(0, objectManager.adapt(Arrays.asList(1L, 2L, 3L)));
 
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isLeft());
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModelStandalone.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModelStandalone.java
index 9996755..d940b0c 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModelStandalone.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModelStandalone.java
@@ -20,6 +20,7 @@ package org.apache.isis.viewer.wicket.model.models;
 
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 import org.apache.isis.viewer.wicket.model.models.interaction.BookmarkedObjectWkt;
 import org.apache.isis.viewer.wicket.model.models.interaction.coll.DataTableModelWkt;
 
@@ -34,7 +35,7 @@ extends EntityCollectionModelAbstract {
     // -- FACTORIES
 
     public static EntityCollectionModelStandalone forActionModel(
-            final @NonNull ManagedObject collectionAsAdapter,
+            final @NonNull PackedManagedObject collectionAsAdapter,
             final @NonNull ActionModel actionModel,
             final @NonNull Can<ManagedObject> args) {
 
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ManagedObjectModel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ManagedObjectModel.java
index a57a6b7..242d8c9 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ManagedObjectModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ManagedObjectModel.java
@@ -34,6 +34,7 @@ import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 
 import lombok.NonNull;
@@ -84,13 +85,13 @@ extends ModelAbstract<ManagedObject> {
         super.setObject(adapter);
 
         if(_Collections.isCollectionOrArrayOrCanType(adapter.getPojo().getClass())) {
-            setObjectCollection(adapter);
+            setObjectCollection((PackedManagedObject)adapter);
         } else {
             memento = super.getMementoService().mementoForObject(adapter);
         }
     }
 
-    public void setObjectCollection(final ManagedObject adapter) {
+    public void setObjectCollection(final PackedManagedObject adapter) {
 
         if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) {
             super.setObject(null);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
index 63ce77e..c517131 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
@@ -28,9 +28,11 @@ import org.apache.isis.applib.value.Clob;
 import org.apache.isis.applib.value.LocalResourcePath;
 import org.apache.isis.applib.value.OpenUrlStrategy;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.PackedManagedObject;
 import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 import org.apache.isis.core.security.authentication.logout.LogoutMenu.LoginRedirect;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
@@ -74,8 +76,10 @@ public enum ActionResultResponseType {
                 final AjaxRequestTarget target,
                 final ManagedObject resultAdapter,
                 final Can<ManagedObject> args) {
+            _Assert.assertTrue(resultAdapter instanceof PackedManagedObject);
+
             final var collectionModel = EntityCollectionModelStandalone
-                    .forActionModel(resultAdapter, actionModel, args);
+                    .forActionModel((PackedManagedObject)resultAdapter, actionModel, args);
             return ActionResultResponse.toPage(
                     StandaloneCollectionPage.class, new StandaloneCollectionPage(collectionModel));
         }
@@ -266,9 +270,12 @@ public enum ActionResultResponseType {
         }
 
         val resultSpec = resultAdapter.getSpecification();
-        if (resultSpec.isNotCollection()) {
+        if (!(resultAdapter instanceof PackedManagedObject)) {
+
             // scalar ...
 
+            _Assert.assertTrue(resultSpec.isNotCollection());
+
             if(LoginRedirect.LOGICAL_TYPE_NAME.equals(resultSpec.getLogicalTypeName())) {
                 return TypeAndAdapter.of(ActionResultResponseType.SIGN_IN, resultAdapter);
             }
@@ -300,15 +307,13 @@ public enum ActionResultResponseType {
         } else {
             // non-scalar ...
 
-            final int cardinality = (int)_NullSafe.streamAutodetect(resultAdapter.getPojo()).count();
+            val packedAdapter = (PackedManagedObject) resultAdapter;
+            val unpacked = packedAdapter.unpack();
+
+            final int cardinality = unpacked.size();
             switch (cardinality) {
             case 1:
-                val firstPojo = _NullSafe.streamAutodetect(resultAdapter.getPojo())
-                    .findFirst()
-                    .get();
-                val firstElement = resultAdapter.getSpecification().getMetaModelContext().getObjectManager()
-                        .adapt(firstPojo);
-
+                val firstElement = unpacked.getFirstOrFail();
                 // recursively unwrap
                 return determineFor(firstElement, targetIfAny);
             default: