From ef175d7ca6fc0f66db527abfaa796edc6744da9c Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Mon, 14 Aug 2017 15:14:02 +0200 Subject: [PATCH] Fix BeanUtils#instantiateClass w/ Kotlin + noarg constructor Issue: SPR-15851 --- .../org/springframework/beans/BeanUtils.java | 5 ++-- .../beans/BeanUtilsKotlinTests.kt | 29 ++++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java index 8760fa4a5a..6d03c4e95e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -734,12 +734,11 @@ public abstract class BeanUtils { * Instantiate a Kotlin class using the provided constructor. * @param ctor the constructor of the Kotlin class to instantiate * @param args the constructor arguments to apply (use null for unspecified parameter if needed) - * @throws BeanInstantiationException if no primary constructor can be found */ - public static T instantiateClass(Constructor ctor, Object... args) { + public static T instantiateClass(Constructor ctor, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { KFunction kotlinConstructor = ReflectJvmMapping.getKotlinFunction(ctor); if (kotlinConstructor == null) { - throw new BeanInstantiationException(ctor.getDeclaringClass(), "No corresponding Kotlin constructor found"); + return ctor.newInstance(args); } List parameters = kotlinConstructor.getParameters(); Map argParameters = new HashMap<>(parameters.size()); diff --git a/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt b/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt index bdcdcf95fa..0cfa1db216 100644 --- a/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt +++ b/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt @@ -29,37 +29,46 @@ class BeanUtilsKotlinTests { @Test fun `Instantiate immutable class`() { val constructor = BeanUtils.findPrimaryConstructor(Foo::class.java)!! - val foo = BeanUtils.instantiateClass(constructor, "bar", 3) - assertEquals("bar", foo.param1) + val foo = BeanUtils.instantiateClass(constructor, "a", 3) + assertEquals("a", foo.param1) assertEquals(3, foo.param2) } @Test fun `Instantiate immutable class with optional parameter and all parameters specified`() { val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!! - val bar = BeanUtils.instantiateClass(constructor, "baz", 8) - assertEquals("baz", bar.param1) + val bar = BeanUtils.instantiateClass(constructor, "a", 8) + assertEquals("a", bar.param1) assertEquals(8, bar.param2) } @Test fun `Instantiate immutable class with optional parameter and only mandatory parameters specified by position`() { val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!! - val bar = BeanUtils.instantiateClass(constructor, "baz") - assertEquals("baz", bar.param1) + val bar = BeanUtils.instantiateClass(constructor, "a") + assertEquals("a", bar.param1) assertEquals(12, bar.param2) } @Test - fun `Instantiate immutable class with optional parameter specified with null value`() { + fun `Instantiate immutable class with optional parameter specified with null value`() { val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!! - val bar = BeanUtils.instantiateClass(constructor, "baz", null) - assertEquals("baz", bar.param1) + val bar = BeanUtils.instantiateClass(constructor, "a", null) + assertEquals("a", bar.param1) assertEquals(12, bar.param2) } + @Test // SPR-15851 + fun `Instantiate mutable class with declared constructor and default values for all parameters`() { + val baz = BeanUtils.instantiateClass(Baz::class.java.getDeclaredConstructor()) + assertEquals("a", baz.param1) + assertEquals(12, baz.param2) + } + class Foo(val param1: String, val param2: Int) class Bar(val param1: String, val param2: Int = 12) - + + class Baz(var param1: String = "a", var param2: Int = 12) + }