From 8eb618b480896092cae04d1c5e412f7a5dba0c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 14 Feb 2022 10:08:42 +0100 Subject: [PATCH] Make Kotlin functions accessible in CoroutinesUtils In order to allow using private classes like in Java for example. Closes gh-23840 --- .../springframework/core/CoroutinesUtils.java | 6 +++++- .../result/KotlinInvocableHandlerMethodTests.kt | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java b/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java index 50aec2deb3a..6770f01c0a0 100644 --- a/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java +++ b/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import kotlin.jvm.JvmClassMappingKt; import kotlin.reflect.KClassifier; import kotlin.reflect.KFunction; import kotlin.reflect.full.KCallables; +import kotlin.reflect.jvm.KCallablesJvm; import kotlin.reflect.jvm.ReflectJvmMapping; import kotlinx.coroutines.BuildersKt; import kotlinx.coroutines.CoroutineStart; @@ -70,6 +71,9 @@ public abstract class CoroutinesUtils { */ public static Publisher invokeSuspendingFunction(Method method, Object target, Object... args) { KFunction function = Objects.requireNonNull(ReflectJvmMapping.getKotlinFunction(method)); + if (method.isAccessible() && !KCallablesJvm.isAccessible(function)) { + KCallablesJvm.setAccessible(function, true); + } KClassifier classifier = function.getReturnType().getClassifier(); Mono mono = MonoKt.mono(Dispatchers.getUnconfined(), (scope, continuation) -> KCallables.callSuspend(function, getSuspendedFunctionArgs(target, args), continuation)) diff --git a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/result/KotlinInvocableHandlerMethodTests.kt b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/result/KotlinInvocableHandlerMethodTests.kt index 8589ddc570f..13304695527 100644 --- a/spring-webflux/src/test/kotlin/org/springframework/web/reactive/result/KotlinInvocableHandlerMethodTests.kt +++ b/spring-webflux/src/test/kotlin/org/springframework/web/reactive/result/KotlinInvocableHandlerMethodTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -97,6 +97,14 @@ class KotlinInvocableHandlerMethodTests { assertThat(this.exchange.response.headers.getFirst("foo")).isEqualTo("bar") } + @Test + fun privateController() { + this.resolvers.add(stubResolver("foo")) + val method = PrivateCoroutinesController::singleArg.javaMethod!! + val result = invoke(PrivateCoroutinesController(), method,"foo") + assertHandlerResultValue(result, "success:foo") + } + private fun invoke(handler: Any, method: Method, vararg providedArgs: Any?): Mono { val invocable = InvocableHandlerMethod(handler, method) invocable.setArgumentResolvers(this.resolvers) @@ -146,7 +154,13 @@ class KotlinInvocableHandlerMethodTests { delay(10) response.headers.add("foo", "bar") } + } + private class PrivateCoroutinesController { + suspend fun singleArg(q: String?): String { + delay(10) + return "success:$q" + } } } \ No newline at end of file