You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/01/29 10:20:56 UTC

[isis] branch master updated: ISIS-2950: [Async Wrapper] fixes mixin proxy creation

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 fffc31f  ISIS-2950: [Async Wrapper] fixes mixin proxy creation
fffc31f is described below

commit fffc31fade4356f84cf121e9c05e1b234e6f3fff
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Jan 29 11:20:48 2022 +0100

    ISIS-2950: [Async Wrapper] fixes mixin proxy creation
    
    - when the minxin's single arg constructor type not exactly matches the
    mixee instance's type; in other words, when inherited
---
 .../progmodel/ProgrammingModelConstants.java       | 31 ++++++++++++++++++++++
 .../factory/FactoryServiceDefault.java             | 14 +++-------
 .../wrapper/WrapperFactoryDefault.java             |  6 ++++-
 3 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
index d2bb56b..dafaf24 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/progmodel/ProgrammingModelConstants.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.config.progmodel;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -42,8 +43,14 @@ import org.apache.isis.applib.annotation.ObjectLifecycle;
 import org.apache.isis.applib.annotation.ObjectSupport;
 import org.apache.isis.applib.services.i18n.TranslatableString;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._Refs;
 import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.commons.internal.reflection._Reflect;
+
+import static org.apache.isis.commons.internal.reflection._Reflect.Filter.paramAssignableFrom;
+import static org.apache.isis.commons.internal.reflection._Reflect.Filter.paramCount;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -115,6 +122,30 @@ public final class ProgrammingModelConstants {
         }
     }
 
+    // -- MIXIN CONSTRUCTION
+
+    public enum MixinConstructor {
+        /**
+         * Assuming, mixins do have a public single argument constructor,
+         * that receive an instance of the mixee's type.
+         */
+        PUBLIC_SINGLE_ARG_RECEIVING_MIXEE;
+
+        // while this enum only has a single value, we just provide a (quasi) static method here
+        public <T> Constructor<T> lookupConstructor(
+                final @NonNull Class<T> mixinClass,
+                final @NonNull Class<?> mixeeClass) {
+            return _Casts.uncheckedCast(_Reflect
+                        .getPublicConstructors(mixinClass)
+                        .filter(paramCount(1).and(paramAssignableFrom(0, mixeeClass)))
+                    .getSingleton()
+                    .orElseThrow(()->_Exceptions.illegalArgument(
+                            "Failed to locate constructor in '%s' to instantiate,"
+                            + "when using type '%s' as first argument",
+                            mixinClass.getName(), mixinClass.getName())));
+        }
+    }
+
     // -- LIFECYCLE CALLBACKS
 
     @Getter
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 4b835a8..cddb527 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
@@ -35,8 +35,8 @@ import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.commons.internal.reflection._Reflect;
 import org.apache.isis.core.config.environment.IsisSystemEnvironment;
+import org.apache.isis.core.config.progmodel.ProgrammingModelConstants.MixinConstructor;
 import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.services.objectlifecycle.ObjectLifecyclePublisher;
@@ -44,9 +44,6 @@ import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
-import static org.apache.isis.commons.internal.reflection._Reflect.Filter.paramAssignableFrom;
-import static org.apache.isis.commons.internal.reflection._Reflect.Filter.paramCount;
-
 import lombok.NonNull;
 import lombok.val;
 
@@ -114,13 +111,8 @@ public class FactoryServiceDefault implements FactoryService {
             throw _Exceptions.illegalArgument("Mixin class '%s' is not a mixin for supplied object '%s'",
                     mixinClass.getName(), mixedIn);
         }
-        val mixinConstructor = _Reflect
-                .getPublicConstructors(mixinClass)
-                        .filter(paramCount(1).and(paramAssignableFrom(0, mixedIn.getClass())))
-                .getSingleton()
-                .orElseThrow(()->_Exceptions.illegalArgument(
-                        "Failed to locate constructor in '%s' to instantiate using '%s'",
-                        mixinClass.getName(), mixedIn));
+        val mixinConstructor = MixinConstructor.PUBLIC_SINGLE_ARG_RECEIVING_MIXEE
+                .lookupConstructor(mixinClass, mixedIn.getClass());
 
         try {
             val mixin = mixinConstructor.newInstance(mixedIn);
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
index 5a22951..cdd51f4 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
@@ -86,6 +86,7 @@ import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.commons.internal.proxy._ProxyFactoryService;
+import org.apache.isis.core.config.progmodel.ProgrammingModelConstants.MixinConstructor;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.interactions.InteractionHead;
 import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
@@ -310,8 +311,11 @@ public class WrapperFactoryDefault implements WrapperFactory {
         val mixeeAdapter = adaptAndGuardAgainstWrappingNotSupported(mixee);
         val mixinAdapter = adaptAndGuardAgainstWrappingNotSupported(mixin);
 
+        val mixinConstructor = MixinConstructor.PUBLIC_SINGLE_ARG_RECEIVING_MIXEE
+                .lookupConstructor(mixinClass, mixee.getClass());
+
         val proxyFactory = proxyFactoryService
-                .factory(mixinClass, new Class[]{WrappingObject.class}, new Class[]{mixee.getClass()});
+                .factory(mixinClass, new Class[]{WrappingObject.class}, mixinConstructor.getParameterTypes());
 
         return proxyFactory.createInstance((proxy, method, args) -> {