How to preserve Context for whole Request with Spring webFlux and coroutines

Right i guess we don’t want myData for both request context but since threadLocal is thread Level and thread can be used by multiple request so myData is automatically shared for both request context even if we don’t want. Maybe another con of using threadLocal in multithreaded asynchronous environment.

I feel you overcomplicate this. Thread local is a simple storage for an object. It doesn’t understand the data it stores, it never modifies it. If we pass a map, it never copies it or clears it of its data. It just keeps it for us.

  1. New request arrives.
  2. We create a new map, specific to this request.
  3. We ask coroutines machinery to set the thread local to our map whenever request/coroutine switches to another thread.
  4. No other requests/coroutines ever touch the same map. If another requests arrives and it is handled by the same thread which handled the first request, it creates another map and assigns it to thread local. This doesn’t affect the first map in any way.

It is really as simple as that.

1 Like

The only thing that concerns me in your approach is that you want to initialize the thread local and add it to the coroutine context in two different places. It would be both cleaner and safer to do both in a single place.

I never used Spring with coroutines, so I’m making educated guesses here, but seeing it provides CoWebFilter, isn’t the whole thing as simple as writing a filter such as:

withContext(myThreadLocal.asContextElement(mutableMapOf())) {
    chain.filter(exchange)
}

And… this is it…?

mutableMapOf() here could be pretty much anything: map or custom object, immutable or mutable, already initialized with data or waiting to be updated during the request processing. The only thing that matters is that we create a new instance in the filter, so each request has a separate object.