diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index b28c7655b0..61566c999c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -34,9 +34,13 @@ import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import kotlin.reflect.KFunction; +import kotlin.reflect.jvm.ReflectJvmMapping; + import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.KotlinDetector; import org.springframework.core.MethodIntrospector; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -585,6 +589,10 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } public void register(T mapping, Object handler, Method method) { + // Assert that the handler method is not a suspending one. + if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) { + throw new IllegalStateException("Unsupported suspending handler method detected: " + method); + } this.readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); @@ -793,4 +801,15 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap } } + /** + * Inner class to avoid a hard dependency on Kotlin at runtime. + */ + private static class KotlinDelegate { + + static private boolean isSuspend(Method method) { + KFunction function = ReflectJvmMapping.getKotlinFunction(method); + return function != null && function.isSuspend(); + } + } + }