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/07/01 07:10:31 UTC

[isis] branch master updated: ISIS-1720: properly handle synthetic methods

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 c9c292d  ISIS-1720: properly handle synthetic methods
c9c292d is described below

commit c9c292d4ef6fb217a32ed715e30559cdfd906a2a
Author: andi-huber <ah...@apache.org>
AuthorDate: Thu Jul 1 09:08:41 2021 +0200

    ISIS-1720: properly handle synthetic methods
---
 .../isis/commons/internal/reflection/_Reflect.java | 17 ++++++++++
 .../core/metamodel/facets/ImperativeFacet.java     |  9 +++++
 ...ctionInvocationFacetForDomainEventAbstract.java |  2 +-
 .../method/ActionDefaultsFacetViaMethod.java       |  2 +-
 .../ActionParameterValidationFacetViaMethod.java   |  2 +-
 .../method/ActionValidationFacetViaMethod.java     |  2 +-
 .../CollectionAccessorFacetViaAccessor.java        |  2 +-
 .../method/DisableForContextFacetViaMethod.java    |  2 +-
 .../method/HideForContextFacetViaMethod.java       |  2 +-
 .../object/callbacks/CallbackFacetAbstract.java    |  7 ++--
 .../method/DisabledObjectFacetViaMethod.java       |  2 +-
 .../TitleFacetInferredFromToStringMethod.java      |  2 +-
 .../title/methods/TitleFacetViaTitleMethod.java    |  2 +-
 .../method/ValidateObjectFacetMethod.java          |  2 +-
 .../ActionParameterAutoCompleteFacetViaMethod.java |  2 +-
 .../method/ActionChoicesFacetViaMethod.java        |  2 +-
 .../ActionParameterChoicesFacetViaMethod.java      |  2 +-
 .../ActionParameterDefaultsFacetViaMethod.java     |  2 +-
 .../ActionParameterDisabledFacetViaMethod.java     |  2 +-
 .../ActionParameterHiddenFacetViaMethod.java       |  2 +-
 .../ActionParameterValidationFacetViaMethod.java   |  2 +-
 .../accessor/PropertyAccessorFacetViaAccessor.java |  2 +-
 .../method/PropertyAutoCompleteFacetMethod.java    |  2 +-
 .../method/PropertyChoicesFacetViaMethod.java      |  2 +-
 .../method/PropertyDefaultFacetViaMethod.java      |  2 +-
 .../clear/PropertyClearFacetViaClearMethod.java    |  2 +-
 .../clear/PropertyClearFacetViaSetterMethod.java   |  2 +-
 ...PropertyInitializationFacetViaSetterMethod.java |  2 +-
 .../modify/PropertySetterFacetViaSetterMethod.java |  2 +-
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 39 ++++++++++++++++++++--
 30 files changed, 94 insertions(+), 30 deletions(-)

diff --git a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
index b755448..6e651b4 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
@@ -33,6 +33,7 @@ import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.function.Consumer;
@@ -559,5 +560,21 @@ public final class _Reflect {
 
     }
 
+    /**
+     * Lookup regular method for a synthetic one in the method's declaring class type-hierarchy.
+     */
+    public static Optional<Method> lookupRegularMethodForSynthetic(final @NonNull Method syntheticMethod) {
+
+        if(!syntheticMethod.isSynthetic()) {
+            return Optional.of(syntheticMethod);
+        }
+
+        return streamTypeHierarchy(syntheticMethod.getDeclaringClass(), InterfacePolicy.INCLUDE)
+        .flatMap(type->_NullSafe.stream(type.getDeclaredMethods()))
+        .filter(method->syntheticMethod.getName().equals(method.getName()))
+        .filter(method->!method.isSynthetic())
+        .findFirst();
+    }
+
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
index 9839a27..d95cadb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
@@ -25,10 +25,13 @@ import java.util.stream.Collectors;
 
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.commons.internal.reflection._Reflect;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
+import lombok.NonNull;
 import lombok.val;
 
 /**
@@ -132,6 +135,12 @@ public interface ImperativeFacet extends Facet {
         throw new IllegalArgumentException(member.getFeatureIdentifier().toString() +  ": unable to determine intent of " + method.getName());
     }
 
+    public static Can<Method> singleMethod(final @NonNull Method method) {
+        return _Reflect
+                .lookupRegularMethodForSynthetic(method)
+                .map(Can::ofSingleton)
+                .orElseThrow(()->_Exceptions.illegalArgument("cannot resolve syntetic method %s to a regular one", method));
+    }
 
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index adff89f..190d1ce 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -74,7 +74,7 @@ implements ImperativeFacet {
 
         super(holder);
         this.eventType = eventType;
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.onType = onType;
         this.returnType = returnType;
         this.serviceRegistry = getServiceRegistry();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
index a7e170b..600ae63 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
@@ -47,7 +47,7 @@ implements ImperativeFacet {
 
     public ActionDefaultsFacetViaMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.actionMethod = determineActionMethod(holder);
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java
index 6431f74..7ab6c19 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java
@@ -47,7 +47,7 @@ implements ImperativeFacet {
     public ActionParameterValidationFacetViaMethod(final Method method, final TranslationService translationService,
     		final TranslationContext translationContext, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
index 9049b58..b551c3a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
@@ -55,7 +55,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
         this.ppmFactory = ppmFactory;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
index 490546d..15093fa 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
@@ -46,7 +46,7 @@ implements ImperativeFacet {
             final Method method,
             final FacetHolder holder) {
         super(typeSpec, holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
index 4ecc18b..99dab69 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
@@ -50,7 +50,7 @@ implements ImperativeFacet {
             final TranslationContext translationContext,
             final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
index 009771e..2806d16 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
@@ -41,7 +41,7 @@ implements ImperativeFacet {
 
     public HideForContextFacetViaMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java
index 461e341..c3b0094 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java
@@ -26,6 +26,7 @@ import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.commons.internal.reflection._Reflect;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -42,7 +43,7 @@ implements CallbackFacet {
     private final List<Method> methods = _Lists.newConcurrentList();
     private final _Lazy<Can<Method>> methodsUnmodifiable = _Lazy.threadSafe(()->Can.ofCollection(methods));
 
-    public CallbackFacetAbstract(final Class<? extends Facet> facetType, final FacetHolder holder) {
+    protected CallbackFacetAbstract(final Class<? extends Facet> facetType, final FacetHolder holder) {
         super(facetType, holder);
     }
 
@@ -57,7 +58,9 @@ implements CallbackFacet {
             throw _Exceptions
                 .illegalState("getMethods() was already called, can no longer add any method: %s", method);
         }
-        methods.add(method);
+        _Reflect
+        .lookupRegularMethodForSynthetic(method)
+        .ifPresent(methods::add);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java
index 0aeac9f..fa9ea1e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java
@@ -52,7 +52,7 @@ implements ImperativeFacet {
             final TranslationContext translationContext,
             final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetInferredFromToStringMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetInferredFromToStringMethod.java
index d964e82..07211d1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetInferredFromToStringMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetInferredFromToStringMethod.java
@@ -39,7 +39,7 @@ implements ImperativeFacet {
 
     public TitleFacetInferredFromToStringMethod(final Method method, final FacetHolder holder) {
         super(holder, Precedence.INFERRED);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java
index 95cf4f0..625242e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java
@@ -49,7 +49,7 @@ implements ImperativeFacet {
     		final TranslationContext translationContext,
     		final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationContext = translationContext;
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/validating/validateobject/method/ValidateObjectFacetMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/validating/validateobject/method/ValidateObjectFacetMethod.java
index f432250..5761bfe 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/validating/validateobject/method/ValidateObjectFacetMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/validating/validateobject/method/ValidateObjectFacetMethod.java
@@ -46,7 +46,7 @@ implements ImperativeFacet {
     public ValidateObjectFacetMethod(final Method method, final TranslationService translationService,
     		final TranslationContext translationContext, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java
index 0d10cb9..6f2bf7a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java
@@ -54,7 +54,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.choicesType = choicesType;
         this.minLength = MinLengthUtil.determineMinLength(method);
         this.ppmFactory = ppmFactory;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
index f5a40db..6b49a1b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
@@ -49,7 +49,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.choicesType = choicesType;
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
index 4f11f51..ebd0e23 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
@@ -53,7 +53,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.choicesType = choicesType;
         this.ppmFactory = ppmFactory;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
index 29313aa..f4ab7bc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
@@ -57,7 +57,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.paramNum = paramNum;
         this.ppmFactory = ppmFactory;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java
index 24fad22..aabedaf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java
@@ -55,7 +55,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
         this.ppmFactory = ppmFactory;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java
index db284db..ede08c3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java
@@ -49,7 +49,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.ppmFactory = ppmFactory;
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java
index 6cd7e8f..941d4ae 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java
@@ -55,7 +55,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.translationService = translationService;
         this.translationContext = translationContext;
         this.ppmFactory = ppmFactory;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
index 3ccd7fa..8f554f7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
@@ -48,7 +48,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(typeSpec, holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java
index e6c6d24..5ee350d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java
@@ -48,7 +48,7 @@ implements ImperativeFacet {
             final Class<?> choicesClass,
             final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.choicesClass = choicesClass;
         this.minLength = MinLengthUtil.determineMinLength(method);
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
index db4cdde..83846a3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
@@ -48,7 +48,7 @@ implements ImperativeFacet {
             final FacetHolder holder) {
 
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
         this.choicesClass = choicesClass;
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
index 41a10f5..7314621 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
@@ -44,7 +44,7 @@ implements ImperativeFacet {
             final Method method,
             final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java
index eca5ffb..74557c3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java
@@ -43,7 +43,7 @@ implements ImperativeFacet {
 
     public PropertyClearFacetViaClearMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java
index 47bd1cb..4bb79cb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java
@@ -43,7 +43,7 @@ implements ImperativeFacet {
 
     public PropertyClearFacetViaSetterMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java
index 78a3717..4c4fa9a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java
@@ -40,7 +40,7 @@ implements ImperativeFacet {
 
     public PropertyInitializationFacetViaSetterMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java
index 9f64123..7fe1d1e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java
@@ -43,7 +43,7 @@ implements ImperativeFacet {
 
     public PropertySetterFacetViaSetterMethod(final Method method, final FacetHolder holder) {
         super(holder);
-        this.methods = Can.ofSingleton(method);
+        this.methods = ImperativeFacet.singleMethod(method);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 94e6a83..5f68468 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -20,6 +20,7 @@
 package org.apache.isis.core.metamodel.specloader.specimpl.dflt;
 
 import java.lang.reflect.Method;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -33,6 +34,7 @@ import org.apache.isis.commons.collections.ImmutableEnumSet;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
+import org.apache.isis.commons.internal.reflection._Reflect;
 import org.apache.isis.core.metamodel.commons.StringExtensions;
 import org.apache.isis.core.metamodel.commons.ToString;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -281,13 +283,22 @@ implements FacetHolder {
         if (membersByMethod == null) {
             this.membersByMethod = catalogueMembers();
         }
-        return Optional.ofNullable(membersByMethod.get(method));
+
+        val member = membersByMethod.get(method);
+        if(member==null) {
+            // also search in super (effectively recursive)
+            return Optional.ofNullable(superclass())
+                    .flatMap(superSpec->superSpec.getMember(method));
+        }
+
+        return Optional.of(member);
     }
 
     private Map<Method, ObjectMember> catalogueMembers() {
         val membersByMethod = _Maps.<Method, ObjectMember>newHashMap();
         cataloguePropertiesAndCollections(membersByMethod::put);
         catalogueActions(membersByMethod::put);
+        postprocessSyntheticMembers(membersByMethod);
         return membersByMethod;
     }
 
@@ -306,9 +317,33 @@ implements FacetHolder {
             userAction.streamFacets(ImperativeFacet.class)
                 .map(ImperativeFacet::getMethods)
                 .flatMap(Can::stream)
-                .forEach(imperativeFacetMethod->onMember.accept(imperativeFacetMethod, userAction)));
+                .forEach(imperativeFacetMethod->
+                onMember.accept(imperativeFacetMethod, userAction)));
+    }
+
+    /**
+     * for any synthetic method also add an entry with its regular method,
+     * as found in the method's declaring class type-hierarchy
+     */
+    private void postprocessSyntheticMembers(HashMap<Method, ObjectMember> membersByMethod) {
+        val syntheticEntries = Can.ofStream(
+            membersByMethod
+            .entrySet()
+            .stream()
+            .filter(entry->entry.getKey().isSynthetic()));
+
+        syntheticEntries
+        .forEach(entry->{
+            val objectMember = entry.getValue();
+            val syntheticMethod = entry.getKey();
+            _Reflect
+            .lookupRegularMethodForSynthetic(syntheticMethod)
+            .ifPresent(regularMethod->
+                membersByMethod.computeIfAbsent(regularMethod, key->objectMember));
+        });
     }
 
+
     // -- toString
 
     @Override