From 8f4befff838fbb67e2055f7f69361a5bfe770293 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 25 Feb 2021 10:24:32 +0100 Subject: [PATCH] Collect constructor type information via Constructor.getParameters(). This commit fixes an issue where we fail to detect all type arguments from a given constructor. calling getGenericParameterTypes in some cases does not include all Types, we now explicitly iterate over the parameters and extract the parameterized type that is used for creating the TypeInformation. Closes: #2313 Original pull request: #2314. --- .../data/util/TypeDiscoverer.java | 12 +++--- ...eferredConstructorDiscovererUnitTests.java | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/src/main/java/org/springframework/data/util/TypeDiscoverer.java index 90d7eda61..97ab4319e 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -20,6 +20,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -175,14 +176,11 @@ class TypeDiscoverer implements TypeInformation { Assert.notNull(constructor, "Constructor must not be null!"); - Type[] types = constructor.getGenericParameterTypes(); - List> result = new ArrayList<>(types.length); - - for (Type parameterType : types) { - result.add(createInfo(parameterType)); + List> parameterTypes = new ArrayList<>(constructor.getParameterCount()); + for(Parameter parameter : constructor.getParameters()) { + parameterTypes.add(createInfo(parameter.getParameterizedType())); } - - return result; + return parameterTypes; } /* diff --git a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java index 43beb6b5a..29349cb2d 100755 --- a/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/PreferredConstructorDiscovererUnitTests.java @@ -33,6 +33,7 @@ import org.springframework.data.util.ClassTypeInformation; * @author Oliver Gierke * @author Roman Rodov * @author Mark Paluch + * @author Christoph Strobl */ public class PreferredConstructorDiscovererUnitTests

> { @@ -112,6 +113,30 @@ public class PreferredConstructorDiscovererUnitTests

{ + + assertThat(ctor.getParameters()).hasSize(2); + assertThat(ctor.getParameters().get(0).getName()).isEqualTo("this$0"); + assertThat(ctor.getParameters().get(1).getName()).isEqualTo("value"); + }); + } + + @Test // GH-2313 + void capturesSuperClassEnclosingTypeParameterOfNonStaticInnerClass() { + + assertThat(PreferredConstructorDiscoverer.discover(NonStaticInnerWithGenericArgUsedInCtor.class)) + .satisfies(ctor -> { + + assertThat(ctor.getParameters()).hasSize(2); + assertThat(ctor.getParameters().get(0).getName()).isEqualTo("this$0"); + assertThat(ctor.getParameters().get(1).getName()).isEqualTo("value"); + }); + } + static class SyntheticConstructor { @PersistenceConstructor private SyntheticConstructor(String x) {} @@ -164,4 +189,22 @@ public class PreferredConstructorDiscovererUnitTests

{ + + protected GenericTypeArgUsedInCtor(T value) {} + } + + + class NonStaticWithGenericTypeArgUsedInCtor { + + protected NonStaticWithGenericTypeArgUsedInCtor(T value) {} + } + + class NonStaticInnerWithGenericArgUsedInCtor extends GenericTypeArgUsedInCtor { + + public NonStaticInnerWithGenericArgUsedInCtor(T value) { + super(value); + } + } }