Support suspending handler methods in Spring MVC
This commit adds support for Kotlin Coroutines suspending functions to Spring MVC, by converting those to a Mono that can then be handled by the asynchronous request processing feature. It also optimizes Coroutines detection with the introduction of an optimized KotlinDetector.isSuspendingFunction() method that does not require kotlin-reflect. Closes gh-23611
This commit is contained in:
@@ -51,14 +51,6 @@ internal fun <T: Any> deferredToMono(source: Deferred<T>) =
|
||||
internal fun <T: Any> monoToDeferred(source: Mono<T>) =
|
||||
GlobalScope.async(Dispatchers.Unconfined) { source.awaitFirstOrNull() }
|
||||
|
||||
/**
|
||||
* Return {@code true} if the method is a suspending function.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.2.2
|
||||
*/
|
||||
internal fun isSuspendingFunction(method: Method) = method.kotlinFunction!!.isSuspend
|
||||
|
||||
/**
|
||||
* Invoke a suspending function and converts it to [Mono] or [reactor.core.publisher.Flux].
|
||||
*
|
||||
@@ -66,7 +58,7 @@ internal fun isSuspendingFunction(method: Method) = method.kotlinFunction!!.isSu
|
||||
* @since 5.2
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun invokeSuspendingFunction(method: Method, bean: Any, vararg args: Any?): Publisher<*> {
|
||||
fun invokeSuspendingFunction(method: Method, bean: Any, vararg args: Any?): Publisher<*> {
|
||||
val function = method.kotlinFunction!!
|
||||
val mono = mono(Dispatchers.Unconfined) {
|
||||
function.callSuspend(bean, *args.sliceArray(0..(args.size-2))).let { if (it == Unit) null else it }
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.core;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -74,4 +75,20 @@ public abstract class KotlinDetector {
|
||||
return (kotlinMetadata != null && clazz.getDeclaredAnnotation(kotlinMetadata) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the method is a suspending function.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.3
|
||||
*/
|
||||
public static boolean isSuspendingFunction(Method method) {
|
||||
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
|
||||
Class<?>[] types = method.getParameterTypes();
|
||||
if ((types.length > 0) && "kotlin.coroutines.Continuation".equals(types[types.length - 1].getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user