Skip to content

Commit 6ab8747

Browse files
committed
Merge branch '6.2.x'
2 parents 84ba6b4 + 0141725 commit 6ab8747

File tree

4 files changed

+94
-16
lines changed

4 files changed

+94
-16
lines changed

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

+22-7
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,10 @@ private static class KotlinDelegate {
316316
Object arg = args[index];
317317
if (!(parameter.isOptional() && arg == null)) {
318318
KType type = parameter.getType();
319-
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
319+
if (!(type.isMarkedNullable() && arg == null)
320+
&& type.getClassifier() instanceof KClass<?> kClass
320321
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
321-
KFunction<?> constructor = Objects.requireNonNull(KClasses.getPrimaryConstructor(kClass));
322-
if (!KCallablesJvm.isAccessible(constructor)) {
323-
KCallablesJvm.setAccessible(constructor, true);
324-
}
325-
arg = constructor.call(arg);
322+
arg = box(kClass, arg);
326323
}
327324
argMap.put(parameter, arg);
328325
}
@@ -337,6 +334,20 @@ private static class KotlinDelegate {
337334
return (result == Unit.INSTANCE ? null : result);
338335
}
339336

337+
private static Object box(KClass<?> kClass, @Nullable Object arg) {
338+
KFunction<?> constructor = Objects.requireNonNull(KClasses.getPrimaryConstructor(kClass));
339+
KType type = constructor.getParameters().get(0).getType();
340+
if (!(type.isMarkedNullable() && arg == null)
341+
&& type.getClassifier() instanceof KClass<?> parameterClass
342+
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(parameterClass))) {
343+
arg = box(parameterClass, arg);
344+
}
345+
if (!KCallablesJvm.isAccessible(constructor)) {
346+
KCallablesJvm.setAccessible(constructor, true);
347+
}
348+
return constructor.call(arg);
349+
}
350+
340351
private static void handleResult(Object result, SynchronousSink<Object> sink) {
341352
if (KotlinDetector.isInlineClass(result.getClass())) {
342353
try {
@@ -357,7 +368,11 @@ private static void handleResult(Object result, SynchronousSink<Object> sink) {
357368
}
358369

359370
private static Object unbox(Object result) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
360-
return result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
371+
Object unboxed = result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
372+
if (KotlinDetector.isInlineClass(unboxed.getClass())) {
373+
return unbox(unboxed);
374+
}
375+
return unboxed;
361376
}
362377
}
363378

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

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -109,12 +109,25 @@ class InvocableHandlerMethodKotlinTests {
109109
Assertions.assertThat(value).isEqualTo(1L)
110110
}
111111

112+
@Test
113+
fun nestedValueClass() {
114+
composite.addResolver(StubArgumentResolver(Long::class.java, 1L))
115+
val value = getInvocable(ValueClassHandler::nestedValueClass.javaMethod!!).invokeForRequest(request, null)
116+
Assertions.assertThat(value).isEqualTo(1L)
117+
}
118+
112119
@Test
113120
fun valueClassReturnValue() {
114121
val value = getInvocable(ValueClassHandler::valueClassReturnValue.javaMethod!!).invokeForRequest(request, null)
115122
Assertions.assertThat(value).isEqualTo("foo")
116123
}
117124

125+
@Test
126+
fun nestedValueClassReturnValue() {
127+
val value = getInvocable(ValueClassHandler::nestedValueClassReturnValue.javaMethod!!).invokeForRequest(request, null)
128+
Assertions.assertThat(value).isEqualTo("foo")
129+
}
130+
118131
@Test
119132
fun resultOfUnitReturnValue() {
120133
val value = getInvocable(ValueClassHandler::resultOfUnitReturnValue.javaMethod!!).invokeForRequest(request, null)
@@ -273,10 +286,14 @@ class InvocableHandlerMethodKotlinTests {
273286

274287
fun valueClassReturnValue() = StringValueClass("foo")
275288

289+
fun nestedValueClassReturnValue() = NestedStringValueClass(StringValueClass("foo"))
290+
276291
fun resultOfUnitReturnValue() = Result.success(Unit)
277292

278293
fun longValueClass(limit: LongValueClass) = limit.value
279294

295+
fun nestedValueClass(limit: ULongValueClass) = limit.value
296+
280297
fun doubleValueClass(limit: DoubleValueClass = DoubleValueClass(3.1)) = limit.value
281298

282299
fun valueClassWithInit(valueClass: ValueClassWithInit) = valueClass
@@ -358,9 +375,15 @@ class InvocableHandlerMethodKotlinTests {
358375
@JvmInline
359376
value class StringValueClass(val value: String)
360377

378+
@JvmInline
379+
value class NestedStringValueClass(val value: StringValueClass)
380+
361381
@JvmInline
362382
value class LongValueClass(val value: Long)
363383

384+
@JvmInline
385+
value class ULongValueClass(val value: ULong)
386+
364387
@JvmInline
365388
value class DoubleValueClass(val value: Double)
366389

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

+22-7
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,10 @@ private static class KotlinDelegate {
354354
Object arg = args[index];
355355
if (!(parameter.isOptional() && arg == null)) {
356356
KType type = parameter.getType();
357-
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
357+
if (!(type.isMarkedNullable() && arg == null)
358+
&& type.getClassifier() instanceof KClass<?> kClass
358359
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
359-
KFunction<?> constructor = Objects.requireNonNull(KClasses.getPrimaryConstructor(kClass));
360-
if (!KCallablesJvm.isAccessible(constructor)) {
361-
KCallablesJvm.setAccessible(constructor, true);
362-
}
363-
arg = constructor.call(arg);
360+
arg = box(kClass, arg);
364361
}
365362
argMap.put(parameter, arg);
366363
}
@@ -376,6 +373,20 @@ private static class KotlinDelegate {
376373
}
377374
}
378375

376+
private static Object box(KClass<?> kClass, @Nullable Object arg) {
377+
KFunction<?> constructor = Objects.requireNonNull(KClasses.getPrimaryConstructor(kClass));
378+
KType type = constructor.getParameters().get(0).getType();
379+
if (!(type.isMarkedNullable() && arg == null)
380+
&& type.getClassifier() instanceof KClass<?> parameterClass
381+
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(parameterClass))) {
382+
arg = box(parameterClass, arg);
383+
}
384+
if (!KCallablesJvm.isAccessible(constructor)) {
385+
KCallablesJvm.setAccessible(constructor, true);
386+
}
387+
return constructor.call(arg);
388+
}
389+
379390
private static void handleResult(Object result, SynchronousSink<Object> sink) {
380391
if (KotlinDetector.isInlineClass(result.getClass())) {
381392
try {
@@ -396,7 +407,11 @@ private static void handleResult(Object result, SynchronousSink<Object> sink) {
396407
}
397408

398409
private static Object unbox(Object result) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
399-
return result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
410+
Object unboxed = result.getClass().getDeclaredMethod("unbox-impl").invoke(result);
411+
if (KotlinDetector.isInlineClass(unboxed.getClass())) {
412+
return unbox(unboxed);
413+
}
414+
return unboxed;
400415
}
401416

402417
}

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -205,13 +205,28 @@ class InvocableHandlerMethodKotlinTests {
205205
assertHandlerResultValue(result, "1")
206206
}
207207

208+
@Test
209+
fun nestedValueClass() {
210+
this.resolvers.add(stubResolver(1L, Long::class.java))
211+
val method = ValueClassController::nestedValueClass.javaMethod!!
212+
val result = invoke(ValueClassController(), method,1L)
213+
assertHandlerResultValue(result, "1")
214+
}
215+
208216
@Test
209217
fun valueClassReturnValue() {
210218
val method = ValueClassController::valueClassReturnValue.javaMethod!!
211219
val result = invoke(ValueClassController(), method)
212220
assertHandlerResultValue(result, "foo")
213221
}
214222

223+
@Test
224+
fun nestedValueClassReturnValue() {
225+
val method = ValueClassController::nestedValueClassReturnValue.javaMethod!!
226+
val result = invoke(ValueClassController(), method)
227+
assertHandlerResultValue(result, "foo")
228+
}
229+
215230
@Test
216231
fun resultOfUnitReturnValue() {
217232
val method = ValueClassController::resultOfUnitReturnValue.javaMethod!!
@@ -448,8 +463,12 @@ class InvocableHandlerMethodKotlinTests {
448463

449464
fun valueClass(limit: LongValueClass) = "${limit.value}"
450465

466+
fun nestedValueClass(limit: ULongValueClass) = "${limit.value}"
467+
451468
fun valueClassReturnValue() = StringValueClass("foo")
452469

470+
fun nestedValueClassReturnValue() = NestedStringValueClass(StringValueClass("foo"))
471+
453472
fun resultOfUnitReturnValue() = Result.success(Unit)
454473

455474
fun valueClassWithDefault(limit: DoubleValueClass = DoubleValueClass(3.1)) = "${limit.value}"
@@ -533,9 +552,15 @@ class InvocableHandlerMethodKotlinTests {
533552
@JvmInline
534553
value class StringValueClass(val value: String)
535554

555+
@JvmInline
556+
value class NestedStringValueClass(val value: StringValueClass)
557+
536558
@JvmInline
537559
value class LongValueClass(val value: Long)
538560

561+
@JvmInline
562+
value class ULongValueClass(val value: ULong)
563+
539564
@JvmInline
540565
value class DoubleValueClass(val value: Double)
541566

0 commit comments

Comments
 (0)