Some JVM frameworks use ThreadLocal to store the call context of a application, like the SLF4j MDC, transaction managers, security managers, and others.
However, Kotlin coroutines are dispatched on different threads, so how it can be made to work?
(The question is inspired by GitHub issue)
Coroutine's analog to
ThreadLocalisCoroutineContext.To interoperate with
ThreadLocal-using libraries you need to implement a customContinuationInterceptorthat supports framework-specific thread-locals.Here is an example. Let us assume that we use some framework that relies on a specific
ThreadLocalto store some application-specific data (MyDatain this example):To use it with coroutines, you'll need to implement a context that keeps the current value of
MyDataand puts it into the correspondingThreadLocalevery time the coroutine is resumed on a thread. The code should look like this:To use it in your coroutines, you wrap the dispatcher that you want to use with
MyContextand give it the initial value of your data. This value will be put into the thread-local on the thread where the coroutine is resumed.The implementation above would also track any changes to the thread-local that was done and store it in this context, so this way multiple invocation can share "thread-local" data via context.
UPDATE: Starting with
kotlinx.corutinesversion0.25.0there is direct support for representing JavaThreadLocalinstances as coroutine context elements. See this documentation for details. There is also out-of-the-box support for SLF4J MDC viakotlinx-coroutines-slf4jintegration module.