From 8460cfee5bc184958e9c7565b2050f9ada0c1435 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 f79107ddf..5fd353583 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -24,6 +24,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; @@ -178,14 +179,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); + } + } }