Skip to content

Commit 5350aea

Browse files
fix: ignore Kotlin DefaultConstructorMarker in BeanUtils#getParametersName (#34760)
Mismatch caused by DefaultConstructorMarker, which is now filtered out. Signed-off-by: EmilSt <[email protected]>
1 parent d8b506e commit 5350aea

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

spring-beans/src/main/java/org/springframework/beans/BeanUtils.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.Set;
3434

3535
import kotlin.jvm.JvmClassMappingKt;
36+
import kotlin.jvm.internal.DefaultConstructorMarker;
3637
import kotlin.reflect.KClass;
3738
import kotlin.reflect.KFunction;
3839
import kotlin.reflect.KParameter;
@@ -659,7 +660,13 @@ public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd) {
659660
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
660661
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
661662
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
662-
Assert.state(paramNames.length == ctor.getParameterCount(),
663+
664+
// The generated param "DefaultConstructorMarker" is used to avoid collision of signatures
665+
// and should be filtered out
666+
long realParamsCount = Arrays.stream(ctor.getParameters())
667+
.filter(p -> !DefaultConstructorMarker.class.equals(p.getType()))
668+
.count();
669+
Assert.state(paramNames.length == realParamsCount,
663670
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);
664671
return paramNames;
665672
}

spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt

+61
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,67 @@ class BeanUtilsKotlinTests {
157157
assertThat(instance).isEqualTo(ConstructorWithNullablePrimitiveValueClass(null))
158158
}
159159

160+
@Test
161+
fun `getParameterNames filters out DefaultConstructorMarker with Foo`() {
162+
val ctor = BeanUtils.findPrimaryConstructor(Foo::class.java)!!
163+
val names = BeanUtils.getParameterNames(ctor)
164+
assertThat(names).containsExactly("param1", "param2")
165+
}
166+
167+
168+
@Test
169+
fun `getParameterNames filters out DefaultConstructorMarker with Bar`() {
170+
val ctor = BeanUtils.findPrimaryConstructor(Bar::class.java)!!
171+
val names = BeanUtils.getParameterNames(ctor)
172+
assertThat(names).containsExactly("param1", "param2")
173+
}
174+
175+
@Test
176+
fun `getParameterNames filters out DefaultConstructorMarker with Baz`() {
177+
val ctor = BeanUtils.findPrimaryConstructor(Baz::class.java)!!
178+
val names = BeanUtils.getParameterNames(ctor)
179+
assertThat(names).containsExactly("param1", "param2")
180+
}
181+
182+
@Test
183+
fun `getParameterNames filters out DefaultConstructorMarker with Qux`() {
184+
val ctor = BeanUtils.findPrimaryConstructor(Qux::class.java)!!
185+
val names = BeanUtils.getParameterNames(ctor)
186+
assertThat(names).containsExactly("param1", "param2")
187+
}
188+
189+
@Test
190+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithValueClass`() {
191+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithValueClass::class.java)!!
192+
assertThat(ctor).isNotNull()
193+
val names = BeanUtils.getParameterNames(ctor)
194+
assertThat(names).containsExactly("value")
195+
}
196+
197+
@Test
198+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullableValueClass`() {
199+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullableValueClass::class.java)!!
200+
assertThat(ctor).isNotNull()
201+
val names = BeanUtils.getParameterNames(ctor)
202+
assertThat(names).containsExactly("value")
203+
}
204+
205+
@Test
206+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithPrimitiveValueClass`() {
207+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithPrimitiveValueClass::class.java)!!
208+
assertThat(ctor).isNotNull()
209+
val names = BeanUtils.getParameterNames(ctor)
210+
assertThat(names).containsExactly("value")
211+
}
212+
213+
@Test
214+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullablePrimitiveValueClass`() {
215+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullablePrimitiveValueClass::class.java)!!
216+
assertThat(ctor).isNotNull()
217+
val names = BeanUtils.getParameterNames(ctor)
218+
assertThat(names).containsExactly("value")
219+
}
220+
160221

161222
class Foo(val param1: String, val param2: Int)
162223

0 commit comments

Comments
 (0)