springspring-mvckotlin-coroutines

Configure default Kotlin coroutine context in Spring MVC


I need to configure default coroutine context for all requests in Spring MVC. For example MDCContext (similar question as this but for MVC not WebFlux).

What I have tried

  1. Hook into Spring - the coroutine code is here but there is no way to change the default behavior (need to change InvocableHandlerMethod.doInvoke implementation)
  2. Use AOP - AOP and coroutines do not play well together

Any ideas?


Solution

  • To add to @Lukas' answer: Starting from Spring 6.0 CoroutineUtils offers an additional invokeSuspendingFunction overload accepting a coroutine context. InvocableHandlerMethod also now offers a protected invokeSuspendingFunction method which can be overriden to utilize this overload, so you don't have to copy-paste code from the original spring classes anymore:

    @Component
    class ContextConfig(): WebMvcRegistrations {
        override fun getRequestMappingHandlerAdapter(): RequestMappingHandlerAdapter =
            CoroutineContextAwareMappingHandler()
    }
    
    class CoroutineContextAwareMappingHandler(): RequestMappingHandlerAdapter() {
        override fun createInvocableHandlerMethod(handlerMethod: HandlerMethod) =
            CoroutineContextAwareInvocableMethod(handlerMethod)
    }
    
    class CoroutineContextAwareInvocableMethod(handlerMethod: HandlerMethod): ServletInvocableHandlerMethod(handlerMethod) {
    
        @Suppress("ReactiveStreamsUnusedPublisher")
        override fun invokeSuspendingFunction(method: Method, target: Any, args: Array<out Any>): Any {
            val coroutineContext = <initalize your context here>
            return CoroutinesUtils.invokeSuspendingFunction(Dispatchers.Unconfined + coroutineContext, method, target, *args)
        }
    }