Skip to content

Commit b1b9ee0

Browse files
committed
Merge branch '6.1.x'
2 parents a30c06b + 1e80694 commit b1b9ee0

File tree

6 files changed

+80
-17
lines changed

6 files changed

+80
-17
lines changed

Diff for: spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,9 @@ public static Publisher<?> invokeSuspendingFunction(
128128
Object arg = args[index];
129129
if (!(parameter.isOptional() && arg == null)) {
130130
KType type = parameter.getType();
131-
if (!(type.isMarkedNullable() && arg == null)) {
132-
KClass<?> kClass = (KClass<?>) type.getClassifier();
133-
if (KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
134-
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
135-
}
131+
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
132+
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
133+
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
136134
}
137135
argMap.put(parameter, arg);
138136
}

Diff for: spring-core/src/test/kotlin/org/springframework/core/CoroutinesUtilsTests.kt

+26
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@ class CoroutinesUtilsTests {
226226
}
227227
}
228228

229+
@Test
230+
fun invokeSuspendingFunctionWithGenericParameter() {
231+
val method = GenericController::class.java.declaredMethods.first { it.name.startsWith("handle") }
232+
val horse = Animal("horse")
233+
val mono = CoroutinesUtils.invokeSuspendingFunction(method, AnimalController(), horse, null) as Mono
234+
runBlocking {
235+
Assertions.assertThat(mono.awaitSingle()).isEqualTo(horse.name)
236+
}
237+
}
238+
229239
suspend fun suspendingFunction(value: String): String {
230240
delay(1)
231241
return value
@@ -293,6 +303,22 @@ class CoroutinesUtilsTests {
293303
return "${this.message}-$limit"
294304
}
295305

306+
interface Named {
307+
val name: String
308+
}
309+
310+
data class Animal(override val name: String) : Named
311+
312+
abstract class GenericController<T : Named> {
313+
314+
suspend fun handle(named: T): String {
315+
delay(1)
316+
return named.name;
317+
}
318+
}
319+
320+
private class AnimalController : GenericController<Animal>()
321+
296322
@JvmInline
297323
value class ValueClass(val value: String)
298324

Diff for: spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,9 @@ public static Object invokeFunction(Method method, Object target, Object[] args)
317317
Object arg = args[index];
318318
if (!(parameter.isOptional() && arg == null)) {
319319
KType type = parameter.getType();
320-
if (!(type.isMarkedNullable() && arg == null)) {
321-
KClass<?> kClass = (KClass<?>) type.getClassifier();
322-
if (KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
323-
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
324-
}
320+
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
321+
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
322+
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
325323
}
326324
argMap.put(parameter, arg);
327325
}

Diff for: spring-web/src/test/kotlin/org/springframework/web/method/support/InvocableHandlerMethodKotlinTests.kt

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest
2525
import org.springframework.web.testfixture.servlet.MockHttpServletResponse
2626

2727
/**
28-
* Kotlin unit tests for {@link InvocableHandlerMethod}.
28+
* Kotlin unit tests for [InvocableHandlerMethod].
2929
*
3030
* @author Sebastien Deleuze
3131
*/
@@ -134,6 +134,14 @@ class InvocableHandlerMethodKotlinTests {
134134
Assertions.assertThat(value).isEqualTo("foo-20")
135135
}
136136

137+
@Test
138+
fun genericParameter() {
139+
val horse = Animal("horse")
140+
composite.addResolver(StubArgumentResolver(Animal::class.java, horse))
141+
val value = getInvocable(AnimalHandler::class.java, Named::class.java).invokeForRequest(request, null)
142+
Assertions.assertThat(value).isEqualTo(horse.name)
143+
}
144+
137145
private fun getInvocable(clazz: Class<*>, vararg argTypes: Class<*>): InvocableHandlerMethod {
138146
val method = ResolvableMethod.on(clazz).argTypes(*argTypes).resolveMethod()
139147
val handlerMethod = InvocableHandlerMethod(clazz.constructors.first().newInstance(), method)
@@ -202,6 +210,19 @@ class InvocableHandlerMethodKotlinTests {
202210
}
203211
}
204212

213+
private abstract class GenericHandler<T : Named> {
214+
215+
fun handle(named: T) = named.name
216+
}
217+
218+
private class AnimalHandler : GenericHandler<Animal>()
219+
220+
interface Named {
221+
val name: String
222+
}
223+
224+
data class Animal(override val name: String) : Named
225+
205226
@JvmInline
206227
value class LongValueClass(val value: Long)
207228

Diff for: spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,9 @@ public static Object invokeFunction(Method method, Object target, Object[] args,
328328
Object arg = args[index];
329329
if (!(parameter.isOptional() && arg == null)) {
330330
KType type = parameter.getType();
331-
if (!(type.isMarkedNullable() && arg == null)) {
332-
KClass<?> kClass = (KClass<?>) type.getClassifier();
333-
if (KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
334-
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
335-
}
331+
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
332+
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
333+
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
336334
}
337335
argMap.put(parameter, arg);
338336
}

Diff for: spring-webflux/src/test/kotlin/org/springframework/web/reactive/result/InvocableHandlerMethodKotlinTests.kt

+22
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ class InvocableHandlerMethodKotlinTests {
249249
assertHandlerResultValue(result, "foo-20")
250250
}
251251

252+
@Test
253+
fun genericParameter() {
254+
val horse = Animal("horse")
255+
this.resolvers.add(stubResolver(horse))
256+
val method = AnimalController::handle.javaMethod!!
257+
val result = invoke(AnimalController(), method, null)
258+
assertHandlerResultValue(result, horse.name)
259+
}
260+
252261

253262
private fun invokeForResult(handler: Any, method: Method, vararg providedArgs: Any): HandlerResult? {
254263
return invoke(handler, method, *providedArgs).block(Duration.ofSeconds(5))
@@ -379,6 +388,19 @@ class InvocableHandlerMethodKotlinTests {
379388
}
380389
}
381390

391+
private abstract class GenericController<T : Named> {
392+
393+
fun handle(named: T) = named.name
394+
}
395+
396+
private class AnimalController : GenericController<Animal>()
397+
398+
interface Named {
399+
val name: String
400+
}
401+
402+
data class Animal(override val name: String) : Named
403+
382404
@JvmInline
383405
value class LongValueClass(val value: Long)
384406

0 commit comments

Comments
 (0)