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/05/14 13:23:31 UTC

[isis] branch master updated: ISIS-2666: add interaction tests w/ non-scalar params

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 0241347  ISIS-2666: add interaction tests w/ non-scalar params
0241347 is described below

commit 0241347a558d9160805da38de03cd56018047106
Author: ahuber@apache.org <ah...@luna>
AuthorDate: Fri May 14 15:23:19 2021 +0200

    ISIS-2666: add interaction tests w/ non-scalar params
---
 .../core/metamodel/methods/MethodFinderUtils.java  |  10 +-
 .../testdomain/interact/ActionInteractionTest.java | 216 ++++++++++++---------
 .../testdomain/interact/SimulatedUiChoices.java    |  37 +++-
 .../testdomain/model/good/ProperMemberSupport.java |  69 ++++++-
 .../model/good/ProperMemberSupport_action3.java    | 111 +++++++++++
 .../model/good/ProperMemberSupport_action4.java    | 107 ++++++++++
 .../interaction/InteractionDemo_biArgEnabled.java  |   4 +-
 ...nt.java => InteractionDemo_biListOfString.java} |  40 ++--
 .../interaction/InteractionDemo_multiEnum.java     |   6 +-
 .../interaction/InteractionDemo_multiInt.java      |  12 +-
 .../{Parameters.java => ParameterSamples.java}     |  41 +++-
 11 files changed, 520 insertions(+), 133 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
index de19e47..75e6c17 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
@@ -137,13 +137,17 @@ public final class MethodFinderUtils {
 
     public static Stream<Method> streamMethods(final Class<?> type, final Can<String> names, final Class<?> returnType) {
         try {
+
             return _NullSafe.stream(type.getMethods())
                     .filter(MethodUtil::isPublic)
                     .filter(MethodUtil::isNotStatic)
                     .filter(method -> names.contains(method.getName()))
-                    .filter(method -> returnType == null ||
-                                      returnType.isAssignableFrom(method.getReturnType()))
-                    ;
+                    .filter(method -> returnType == null
+                            || returnType.isAssignableFrom(method.getReturnType())
+//XXX for non-scalar types we should probably be a bit smarter
+//                            || (Iterable.class.isAssignableFrom(returnType)
+//                                    && Iterable.class.isAssignableFrom(method.getReturnType()))
+                            );
         } catch (final SecurityException e) {
             log.error("failed to enumerate methods of class %s", type);
             return Stream.empty();
diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
index 4f93730..fccbb12 100644
--- a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
+++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
@@ -18,35 +18,39 @@
  */
 package org.apache.isis.testdomain.interact;
 
+import java.util.List;
+
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.TestPropertySource;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.config.presets.IsisPresets;
 import org.apache.isis.testdomain.conf.Configuration_headless;
 import org.apache.isis.testdomain.model.interaction.Configuration_usingInteractionDomain;
 import org.apache.isis.testdomain.model.interaction.DemoEnum;
 import org.apache.isis.testdomain.model.interaction.InteractionDemo;
 import org.apache.isis.testdomain.model.interaction.InteractionDemo_biArgEnabled;
+import org.apache.isis.testdomain.model.interaction.InteractionDemo_biListOfString;
 import org.apache.isis.testdomain.model.interaction.InteractionDemo_multiEnum;
 import org.apache.isis.testdomain.model.interaction.InteractionDemo_multiInt;
 import org.apache.isis.testdomain.util.interaction.InteractionTestAbstract;
 import org.apache.isis.viewer.common.model.decorator.disable.DisablingUiModel;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import lombok.val;
 
 @SpringBootTest(
-        classes = { 
+        classes = {
                 Configuration_headless.class,
                 Configuration_usingInteractionDomain.class
-        }, 
+        },
         properties = {
                 "isis.core.meta-model.introspector.mode=FULL",
                 "isis.applib.annotation.domain-object.editing=TRUE",
@@ -61,21 +65,21 @@ import lombok.val;
 })
 class ActionInteractionTest extends InteractionTestAbstract {
 
-    @Test 
+    @Test
     void whenEnabled_shouldHaveNoVeto() {
 
         val managedAction = startActionInteractionOn(InteractionDemo.class, "noArgEnabled", Where.OBJECT_FORMS)
-                .getManagedAction().get(); // should not throw  
+                .getManagedAction().get(); // should not throw
 
         assertFalse(managedAction.checkVisibility().isPresent()); // is visible
-        assertFalse(managedAction.checkUsability().isPresent()); // can invoke 
+        assertFalse(managedAction.checkUsability().isPresent()); // can invoke
     }
-    
-    @Test 
+
+    @Test
     void whenDisabled_shouldHaveVeto() {
 
         val managedAction = startActionInteractionOn(InteractionDemo.class, "noArgDisabled", Where.OBJECT_FORMS)
-                .getManagedAction().get(); // should not throw  
+                .getManagedAction().get(); // should not throw
 
 
         assertFalse(managedAction.checkVisibility().isPresent()); // is visible
@@ -87,7 +91,7 @@ class ActionInteractionTest extends InteractionTestAbstract {
         assertEquals("Disabled for demonstration.", veto.getReason());
     }
 
-    @Test 
+    @Test
     void whenEnabled_shouldProvideProperDecoratorModels() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "noArgEnabled", Where.OBJECT_FORMS)
@@ -98,7 +102,7 @@ class ActionInteractionTest extends InteractionTestAbstract {
         assertFalse(disablingUiModel.isPresent());
     }
 
-    @Test 
+    @Test
     void whenDisabled_shouldProvideProperDecoratorModels() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "noArgDisabled", Where.OBJECT_FORMS)
@@ -109,7 +113,7 @@ class ActionInteractionTest extends InteractionTestAbstract {
         assertEquals("Disabled for demonstration.", disablingUiModel.getReason());
     }
 
-    @Test 
+    @Test
     void whenEnabled_shouldProvideActionMetadata() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
@@ -122,31 +126,31 @@ class ActionInteractionTest extends InteractionTestAbstract {
 
     }
 
-    @Test    
+    @Test
     void mixinwhenDisabled_shouldProvideActionMetadata() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgDisabled", Where.OBJECT_FORMS)
                 .checkVisibility()
                 .checkUsability();
-        
+
         assertFalse(actionInteraction.getManagedAction().isPresent()); // since usability should be vetoed
         assertTrue(actionInteraction.getMetamodel().isPresent()); // but should always provide access to metamodel
-        
+
         val actionMeta = actionInteraction.getMetamodel().get();
         assertEquals(2, actionMeta.getParameterCount());
     }
-    
+
     @Test
     void whenEnabled_shouldAllowInvocation() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "noArgEnabled", Where.OBJECT_FORMS)
         .checkVisibility()
         .checkUsability();
-        
+
         val pendingArgs = actionInteraction.startParameterNegotiation().get();
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isLeft());
-        assertEquals(99, (int)resultOrVeto.leftIfAny().getPojo());    
+        assertEquals(99, (int)resultOrVeto.leftIfAny().getPojo());
     }
 
     @Test
@@ -155,34 +159,34 @@ class ActionInteractionTest extends InteractionTestAbstract {
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "noArgDisabled", Where.OBJECT_FORMS)
         .checkVisibility()
         .checkUsability();
-        
+
         assertFalse(actionInteraction.startParameterNegotiation().isPresent());
 
         // even though when assembling valid parameters ...
         val pendingArgs = startActionInteractionOn(InteractionDemo.class, "noArgDisabled", Where.OBJECT_FORMS)
                 .startParameterNegotiation().get();
-        
+
         // we should not be able to invoke the action
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isRight());
-        
+
     }
-    
+
     @Test
     void withParams_shouldProduceCorrectResult() throws Throwable {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
         .checkVisibility()
         .checkUsability();
-        
+
         val params = Can.of(objectManager.adapt(12), objectManager.adapt(34));
-        
+
         val pendingArgs = actionInteraction.startParameterNegotiation().get();
         pendingArgs.setParamValues(params);
-        
+
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isLeft());
-        
+
         assertEquals(46, (int)resultOrVeto.leftIfAny().getPojo());
     }
 
@@ -192,38 +196,38 @@ class ActionInteractionTest extends InteractionTestAbstract {
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
         .checkVisibility()
         .checkUsability();
-        
+
         val params = Can.of(objectManager.adapt(12), objectManager.adapt(34), objectManager.adapt(99));
-        
+
         val pendingArgs = actionInteraction.startParameterNegotiation().get();
         pendingArgs.setParamValues(params);
-        
+
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isLeft());
-        
+
         assertEquals(46, (int)resultOrVeto.leftIfAny().getPojo());
     }
-    
+
     @Test
     void withTooLittleParams_shouldIgnoreUnderflow() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
         .checkVisibility()
         .checkUsability();
-        
+
         val params = Can.of(objectManager.adapt(12));
-        
+
         val pendingArgs = actionInteraction.startParameterNegotiation().get();
         pendingArgs.setParamValues(params);
-        
+
         val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
         assertTrue(resultOrVeto.isLeft());
-        
+
         assertEquals(12, (int)resultOrVeto.leftIfAny().getPojo());
 
     }
-    
-    @Test 
+
+    @Test
     void shouldProvideParameterDefaults() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
@@ -232,17 +236,17 @@ class ActionInteractionTest extends InteractionTestAbstract {
 
         val managedAction = actionInteraction.getManagedAction().get(); // should not throw
         val pendingArgs = managedAction.getInteractionHead().defaults();
-     
+
         val expectedDefaults = Can.of(
                 new InteractionDemo_biArgEnabled(null).defaultA(null),
                 0);
         val actualDefaults = pendingArgs.getParamValues();
-        
+
         assertComponentWiseUnwrappedEquals(expectedDefaults, actualDefaults);
 
     }
-    
-    @Test 
+
+    @Test
     void whenHavingChoices_shouldProvideProperParameterDefaults() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "multiInt", Where.OBJECT_FORMS)
@@ -251,34 +255,34 @@ class ActionInteractionTest extends InteractionTestAbstract {
 
         val managedAction = actionInteraction.getManagedAction().get(); // should not throw
         val pendingArgs = managedAction.getInteractionHead().defaults();
-     
+
         val mixin = new InteractionDemo_multiInt(null);
         val expectedDefaults = Can.<Integer>of(
                 mixin.defaultA(null),
                 mixin.defaultB(null),
                 mixin.defaultC(null));
-        
+
         assertComponentWiseUnwrappedEquals(expectedDefaults, pendingArgs.getParamValues());
-        
+
         // when changing the first parameter, consecutive parameters should not be affected
         // (unless they are depending on this choice ... subject to another test)
-        
+
         int choiceParamNr = 0;
-        
+
         SimulatedUiChoices uiParam = new SimulatedUiChoices();
         uiParam.bind(pendingArgs, choiceParamNr); // bind to param that has choices
         uiParam.simulateChoiceSelect(3); // select 4th choice
-        
+
         val expectedParamsAfter = Can.<Integer>of(
                 mixin.choicesA(null)[3],
                 mixin.defaultB(null),
                 mixin.defaultC(null));
-        
+
         assertComponentWiseUnwrappedEquals(expectedParamsAfter, pendingArgs.getParamValues());
-        
+
     }
-    
-    @Test 
+
+    @Test
     void whenHavingEnumChoices_shouldProvideProperParameterDefaults() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "multiEnum", Where.OBJECT_FORMS)
@@ -287,34 +291,72 @@ class ActionInteractionTest extends InteractionTestAbstract {
 
         val managedAction = actionInteraction.getManagedAction().get(); // should not throw
         val pendingArgs = managedAction.getInteractionHead().defaults();
-     
+
         val mixin = new InteractionDemo_multiEnum(null);
         val expectedDefaults = Can.<DemoEnum>of(
                 mixin.defaultA(null),
                 mixin.defaultB(null),
                 mixin.defaultC(null));
-        
+
         assertComponentWiseUnwrappedEquals(expectedDefaults, pendingArgs.getParamValues());
-        
+
         // when changing the first parameter, consecutive parameters should not be affected
         // (unless they are depending on this choice ... subject to another test)
-        
+
         int choiceParamNr = 0;
-        
+
         SimulatedUiChoices uiParam = new SimulatedUiChoices();
         uiParam.bind(pendingArgs, choiceParamNr); // bind to param that has choices
         uiParam.simulateChoiceSelect(3); // select 4th choice
-        
+
         val expectedParamsAfter = Can.<DemoEnum>of(
                 DemoEnum.values()[3],
                 mixin.defaultB(null),
                 mixin.defaultC(null));
-        
+
+        assertComponentWiseUnwrappedEquals(expectedParamsAfter, pendingArgs.getParamValues());
+    }
+
+    @Test
+    void whenHavingListOfStringChoices_shouldProvideProperParameterDefaults() {
+
+        val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biListOfString", Where.OBJECT_FORMS)
+                .checkVisibility()
+                .checkUsability();
+
+        val managedAction = actionInteraction.getManagedAction().get(); // should not throw
+        val pendingArgs = managedAction.getInteractionHead().defaults();
+
+        val mixin = new InteractionDemo_biListOfString(null);
+        val expectedDefaults = Can.<List<String>>of(
+                mixin.defaultA(null),
+                mixin.defaultB(null));
+
+        assertComponentWiseUnwrappedEquals(expectedDefaults, pendingArgs.getParamValues());
+
+        // when changing the first parameter, consecutive parameters should not be affected
+        // (unless they are depending on this choice ... subject to another test)
+
+        int choiceParamNr = 0;
+
+        SimulatedUiChoices uiParamA = new SimulatedUiChoices();
+        uiParamA.bind(pendingArgs, choiceParamNr); // bind to param that has choices
+        uiParamA.simulateMultiChoiceSelect(0, 2); // select first and 3rd choice
+
+        val expectedParamsAfter = Can.<List<String>>of(
+                _Lists.of(
+                        mixin.defaultA(null).get(0),
+                        mixin.defaultA(null).get(2)
+                        ),
+                _Lists.of(
+                        mixin.defaultB(null).get(0)
+                        ));
+
         assertComponentWiseUnwrappedEquals(expectedParamsAfter, pendingArgs.getParamValues());
     }
-    
-    
-    @Test 
+
+
+    @Test
     void shouldProvideChoices() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
@@ -323,21 +365,21 @@ class ActionInteractionTest extends InteractionTestAbstract {
 
         assertTrue(actionInteraction.getManagedAction().isPresent(), "action is expected to be usable");
 
-        val managedAction = actionInteraction.getManagedAction().get(); 
+        val managedAction = actionInteraction.getManagedAction().get();
         val pendingArgs = managedAction.startParameterNegotiation();
 
         val param0Choices = pendingArgs.getObservableParamChoices(0); // observable
         val param1Choices = pendingArgs.getObservableParamChoices(1); // observable
-        
+
         assertTrue(param0Choices.getValue().isEmpty());
-        
+
         val expectedChoices = new InteractionDemo_biArgEnabled(null).choicesB(null);
         val actualChoices = param1Choices.getValue();
-        
+
         assertComponentWiseUnwrappedEquals(expectedChoices, actualChoices);
     }
-    
-    @Test 
+
+    @Test
     void shouldProvideParameterBinding() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS)
@@ -345,55 +387,55 @@ class ActionInteractionTest extends InteractionTestAbstract {
                 .checkUsability();
 
         assertTrue(actionInteraction.getManagedAction().isPresent(), "action is expected to be usable");
-        
+
         val managedAction = actionInteraction.getManagedAction().get();
         val pendingArgs = managedAction.startParameterNegotiation();
-        
+
         final int firstParamNr = 0;
-        
+
         SimulatedUiComponent uiParam0 = new SimulatedUiComponent();
         uiParam0.bind(pendingArgs.getParamModels().getElseFail(firstParamNr)); // bind to first param
-        
+
         // UI component's value should be initialized to initial defaults
         assertEquals(new InteractionDemo_biArgEnabled(null).defaultA(null), uiParam0.getValue().getPojo());
-        
+
         uiParam0.simulateValueChange(6);
         // simulated change should have been propagated to the backend/model
         assertEquals(6, pendingArgs.getParamValue(firstParamNr).getPojo());
-        
+
         final int choiceParamNr = 1;
-        
+
         SimulatedUiChoices uiParam1 = new SimulatedUiChoices();
         uiParam1.bind(pendingArgs, choiceParamNr); // bind to param that has choices
         uiParam1.simulateChoiceSelect(2); // select 3rd choice
 
         val expectedChoices = new InteractionDemo_biArgEnabled(null).choicesB(null);
         val expectedChoice = expectedChoices[2]; // actual 3rd choice
-        
+
         Object actualChoiceAsSeenByBackend = pendingArgs.getParamValue(choiceParamNr).getPojo();
         Object actualChoiceAsSeenByUi = uiParam1.getValue().getPojo();
 
         assertEquals(expectedChoice, actualChoiceAsSeenByBackend);
         assertEquals(expectedChoice, actualChoiceAsSeenByUi);
-        
+
         // ensure backend changes are reflected back to the UI
-        
+
         val expectedChoiceAfterBackendUpdated = expectedChoices[0]; // actual first choice
         val newParamValue = pendingArgs
                 .adaptParamValuePojo(choiceParamNr, expectedChoiceAfterBackendUpdated);
-        
+
         val bindableParamValue = pendingArgs.getBindableParamValue(choiceParamNr);
         bindableParamValue.setValue(newParamValue);
-        
+
         actualChoiceAsSeenByBackend = pendingArgs.getParamValue(choiceParamNr).getPojo();
         actualChoiceAsSeenByUi = uiParam1.getValue().getPojo();
-        
+
         assertEquals(expectedChoiceAfterBackendUpdated, actualChoiceAsSeenByBackend);
         assertEquals(expectedChoiceAfterBackendUpdated, actualChoiceAsSeenByUi);
-        
+
     }
-    
-  //TODO also deal with non-scalar parameter values 
+
+  //TODO also deal with non-scalar parameter values
   //TODO test whether actions do emit their domain events
   //TODO test whether actions can be vetoed via domain event interception
   //TODO test command reification
diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/SimulatedUiChoices.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/SimulatedUiChoices.java
index 578bec4..96373ab 100644
--- a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/SimulatedUiChoices.java
+++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/SimulatedUiChoices.java
@@ -26,30 +26,40 @@ import org.apache.isis.commons.internal.binding._Bindables;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedValue;
 import org.apache.isis.core.metamodel.interactions.managed.ParameterNegotiationModel;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 import lombok.Getter;
+import lombok.val;
 
 public class SimulatedUiChoices extends HasValueValidation {
 
     private final Bindable<Can<ManagedObject>> choiceBox = _Bindables.empty();
     private final Bindable<ManagedObject> selectedItem = _Bindables.empty();
-    
+
     @Getter private final LongAdder choiceBoxUpdateEventCount = new LongAdder();
     @Getter private final LongAdder selectedItemUpdateEventCount = new LongAdder();
-    
+
+    private ObjectSpecification valueSpecification;
+
+    @Override
     public void bind(ManagedValue managedValue) {
+
+        val choices = managedValue.getChoices();
+
         choiceBox.bind(managedValue.getChoices());
         choiceBox.addListener((e,o,n)->{
             choiceBoxUpdateEventCount.increment();
         });
         selectedItem.bindBidirectional(managedValue.getValue());
         super.bind(managedValue);
-        
+
         selectedItem.addListener((e,o,n)->{
             selectedItemUpdateEventCount.increment();
         });
+
+        valueSpecification = managedValue.getSpecification();
     }
-    
+
     public void bind(ParameterNegotiationModel pendingArgs, int paramNr) {
         bind(pendingArgs.getParamModels().getElseFail(paramNr));
     }
@@ -58,12 +68,23 @@ public class SimulatedUiChoices extends HasValueValidation {
         selectedItem.setValue(choiceBox.getValue().getElseFail(choiceIndex));
     }
 
+    // assuming the parameter is a non-scalar type
+    public void simulateMultiChoiceSelect(int ... choiceIndices) {
+        val newValuePojos = choiceBox.getValue()
+                .pickByIndex(choiceIndices)
+                .map(ManagedObject::getPojo);
+        val newValue = ManagedObject.of(
+                valueSpecification,
+                newValuePojos.toList());
+        selectedItem.setValue(newValue);
+    }
+
     public ManagedObject getValue() {
-        return selectedItem.getValue(); 
+        return selectedItem.getValue();
     }
-    
+
     public Can<ManagedObject> getChoices() {
-        return choiceBox.getValue(); 
+        return choiceBox.getValue();
     }
-    
+
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport.java
index f9e99da..f56c585 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport.java
@@ -22,10 +22,10 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.Collection;
 import org.apache.isis.applib.annotation.CollectionLayout;
 import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.MemberSupport;
 import org.apache.isis.applib.annotation.MinLength;
 import org.apache.isis.applib.annotation.Nature;
 import org.apache.isis.applib.annotation.Property;
@@ -188,4 +188,71 @@ public class ProperMemberSupport {
         return false;
     }
 
+    // -- PROPER ACTION - NEW PARAMETER MODEL - XXX only supported with mixins yet
+/*
+    @Value @Accessors(fluent = true)
+    public static class Parameter {
+        List<String> a;
+        List<String> b;
+    }
+
+    public ProperMemberSupport act(List<String> a, List<String> b) {
+        return this;
+    }
+
+    @MemberSupport
+    public String disableAct() {
+        return null;
+    }
+
+    @MemberSupport
+    public boolean hideAct() {
+        return false;
+    }
+
+    @MemberSupport
+    public String validateAct(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoComplete0Act(Parameter params, @MinLength(3) String search) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoComplete1Act(Parameter params, @MinLength(3) String search) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> choices0Act(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> choices1Act(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public List<String> default0Act(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public List<String> default1Act(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public String validate0Act(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public String validate1Act(Parameter params) {
+        return null;
+    }
+*/
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action3.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action3.java
new file mode 100644
index 0000000..7bad058
--- /dev/null
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action3.java
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.testdomain.model.good;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.applib.annotation.MinLength;
+import org.apache.isis.applib.annotation.Publishing;
+
+import lombok.RequiredArgsConstructor;
+
+@Action(executionPublishing = Publishing.ENABLED)
+@RequiredArgsConstructor
+public class ProperMemberSupport_action3 {
+
+    private final ProperMemberSupport holder;
+
+    // proper mix-in action
+
+    public ProperMemberSupport act(List<String> p0, List<String> p1) {
+        return holder;
+    }
+
+    @MemberSupport
+    public String disableAct() {
+        return null;
+    }
+
+    @MemberSupport
+    public boolean hideAct() {
+        return false;
+    }
+
+    @MemberSupport
+    public String validateAct(List<String> p0, List<String> p1) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoComplete0Act(@MinLength(3) String search) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoComplete1Act(@MinLength(3) String search) {
+        return null;
+    }
+
+// variant with dependent arg
+//    @MemberSupport
+//    public Set<String> autoComplete1$$(String p0, @MinLength(3) String search) {
+//        return null;
+//    }
+
+    @MemberSupport
+    public Set<String> choices0Act() {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> choices1Act() {
+        return null;
+    }
+
+// variant with dependent arg
+//    @MemberSupport
+//    public Set<String> choices1$$(String p0) {
+//        return null;
+//    }
+
+    @MemberSupport
+    public List<String> default0Act() {
+        return null;
+    }
+
+    @MemberSupport
+    public List<String> default1Act() {
+        return null;
+    }
+
+    @MemberSupport
+    public String validate0Act(List<String> p0) {
+        return null;
+    }
+
+    @MemberSupport
+    public String validate1Act(List<String> p1) {
+        return null;
+    }
+
+
+}
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action4.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action4.java
new file mode 100644
index 0000000..365e13b
--- /dev/null
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupport_action4.java
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.testdomain.model.good;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.applib.annotation.MinLength;
+import org.apache.isis.applib.annotation.Publishing;
+
+import lombok.RequiredArgsConstructor;
+import lombok.Value;
+import lombok.experimental.Accessors;
+
+@Action(executionPublishing = Publishing.ENABLED)
+@RequiredArgsConstructor
+public class ProperMemberSupport_action4 {
+
+    private final ProperMemberSupport holder;
+
+    @Value @Accessors(fluent = true)
+    public static class Parameter {
+        List<String> a;
+        List<String> b;
+    }
+
+    // proper mix-in action
+
+    public ProperMemberSupport act(List<String> a, List<String> b) {
+        return holder;
+    }
+
+    @MemberSupport
+    public String disableAct() {
+        return null;
+    }
+
+    @MemberSupport
+    public boolean hideAct() {
+        return false;
+    }
+
+    @MemberSupport
+    public String validateAct(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoCompleteA(Parameter params, @MinLength(3) String search) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> autoCompleteB(Parameter params, @MinLength(3) String search) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> choicesA(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public Set<String> choicesB(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public List<String> defaultA(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public List<String> defaultB(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public String validateA(Parameter params) {
+        return null;
+    }
+
+    @MemberSupport
+    public String validateB(Parameter params) {
+        return null;
+    }
+
+
+}
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biArgEnabled.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biArgEnabled.java
index dcfde10..b3959ae 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biArgEnabled.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biArgEnabled.java
@@ -36,12 +36,12 @@ public class InteractionDemo_biArgEnabled {
     }
 
     @MemberSupport
-    public int defaultA(Parameters.BiInt p) {
+    public int defaultA(ParameterSamples.BiInt p) {
         return 5;
     }
 
     @MemberSupport
-    public int[] choicesB(Parameters.BiInt p) {
+    public int[] choicesB(ParameterSamples.BiInt p) {
         return new int[] {1, 2, 3, 4};
     }
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biListOfString.java
similarity index 61%
copy from regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java
copy to regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biListOfString.java
index e0872c3..4e5e0b7 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_biListOfString.java
@@ -18,56 +18,52 @@
  */
 package org.apache.isis.testdomain.model.interaction;
 
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.MemberSupport;
+import org.apache.isis.commons.internal.collections._Lists;
 
 import lombok.RequiredArgsConstructor;
 
 @Action
 @RequiredArgsConstructor
-public class InteractionDemo_multiInt {
+public class InteractionDemo_biListOfString {
 
     @SuppressWarnings("unused")
     private final InteractionDemo holder;
 
     @MemberSupport
-    public int act(int a, int b, int c) {
-        return a * (b + c);
+    public String act(List<String> a, List<String> b) {
+        return Stream.concat(a.stream(), b.stream())
+                .collect(Collectors.joining(","));
     }
 
     // -- PARAM A
 
     @MemberSupport
-    public int defaultA(Parameters.TriInt p) {
-        return 2;
+    public List<String> defaultA(ParameterSamples.BiListOfString p) {
+        return _Lists.of("a1", "a2", "a3");
     }
 
     @MemberSupport
-    public int[] choicesA(Parameters.TriInt p) {
-        return new int[] {1, 2, 3, 4};
+    public List<String> choicesA(ParameterSamples.BiListOfString p) {
+        return _Lists.of("a1", "a2", "a3", "a4");
     }
 
-    // -- PARAM B
 
-    @MemberSupport
-    public int defaultB(Parameters.TriInt p) {
-        return 3;
-    }
+    // -- PARAM B
 
     @MemberSupport
-    public int[] choicesB(Parameters.TriInt p) {
-        return new int[] {1, 2, 3, 4};
+    public List<String> defaultB(ParameterSamples.BiListOfString p) {
+        return _Lists.of("b1");
     }
 
-    // -- PARAM C
-
     @MemberSupport
-    public int defaultC(Parameters.TriInt p) {
-        return 4;
+    public List<String> choicesB(ParameterSamples.BiListOfString p) {
+        return _Lists.of("b1", "b2", "b3", "b4");
     }
 
-    @MemberSupport
-    public int[] choicesC(Parameters.TriInt p) {
-        return new int[] {1, 2, 3, 4};
-    }
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiEnum.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiEnum.java
index 3984614..aacc713 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiEnum.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiEnum.java
@@ -38,21 +38,21 @@ public class InteractionDemo_multiEnum {
     // -- PARAM A
 
     @MemberSupport
-    public DemoEnum defaultA(Parameters.TriEnum p) {
+    public DemoEnum defaultA(ParameterSamples.TriEnum p) {
         return DemoEnum.values()[1];
     }
 
     // -- PARAM B
 
     @MemberSupport
-    public DemoEnum defaultB(Parameters.TriEnum p) {
+    public DemoEnum defaultB(ParameterSamples.TriEnum p) {
         return DemoEnum.values()[2];
     }
 
     // -- PARAM C
 
     @MemberSupport
-    public DemoEnum defaultC(Parameters.TriEnum p) {
+    public DemoEnum defaultC(ParameterSamples.TriEnum p) {
         return DemoEnum.values()[3];
     }
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java
index e0872c3..0b1a2d1 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/InteractionDemo_multiInt.java
@@ -38,36 +38,36 @@ public class InteractionDemo_multiInt {
     // -- PARAM A
 
     @MemberSupport
-    public int defaultA(Parameters.TriInt p) {
+    public int defaultA(ParameterSamples.TriInt p) {
         return 2;
     }
 
     @MemberSupport
-    public int[] choicesA(Parameters.TriInt p) {
+    public int[] choicesA(ParameterSamples.TriInt p) {
         return new int[] {1, 2, 3, 4};
     }
 
     // -- PARAM B
 
     @MemberSupport
-    public int defaultB(Parameters.TriInt p) {
+    public int defaultB(ParameterSamples.TriInt p) {
         return 3;
     }
 
     @MemberSupport
-    public int[] choicesB(Parameters.TriInt p) {
+    public int[] choicesB(ParameterSamples.TriInt p) {
         return new int[] {1, 2, 3, 4};
     }
 
     // -- PARAM C
 
     @MemberSupport
-    public int defaultC(Parameters.TriInt p) {
+    public int defaultC(ParameterSamples.TriInt p) {
         return 4;
     }
 
     @MemberSupport
-    public int[] choicesC(Parameters.TriInt p) {
+    public int[] choicesC(ParameterSamples.TriInt p) {
         return new int[] {1, 2, 3, 4};
     }
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/Parameters.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/ParameterSamples.java
similarity index 61%
rename from regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/Parameters.java
rename to regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/ParameterSamples.java
index 4750cb5..c87684b 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/Parameters.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/interaction/ParameterSamples.java
@@ -18,10 +18,16 @@
  */
 package org.apache.isis.testdomain.model.interaction;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
 import lombok.Value;
 import lombok.experimental.Accessors;
 
-final class Parameters {
+final class ParameterSamples {
+
+    // -- SCALAR PARAMS
 
     @Value @Accessors(fluent = true)
     public static class BiInt {
@@ -43,4 +49,37 @@ final class Parameters {
         DemoEnum c;
     }
 
+    // -- NON SCALAR PARAMS
+
+    @Value @Accessors(fluent = true)
+    public static class BiListOfString {
+        List<String> a;
+        List<String> b;
+    }
+
+    @Value @Accessors(fluent = true)
+    public static class BiSetOfString {
+        Set<String> a;
+        Set<String> b;
+    }
+
+    @Value @Accessors(fluent = true)
+    public static class BiArrayOfInt {
+        int[] a;
+        int[] b;
+    }
+
+    @Value @Accessors(fluent = true)
+    public static class BiArrayOfEnum {
+        DemoEnum[] a;
+        DemoEnum[] b;
+    }
+
+    @Value @Accessors(fluent = true)
+    public static class BiCollectionOfEnum {
+        Collection<DemoEnum> a;
+        Collection<DemoEnum> b;
+    }
+
+
 }