when using spring webflux and kotlin coroutines, I...
# spring
j
when using spring webflux and kotlin coroutines, I would like to add a header value to MDC. We already have a standard webfilter that adds the header value from the request to the reactor context. Now I want my app to read that value from the reactor-context and then put it on the MDC. I created my own WebFilter and using Mono.deferContextual I am able to get the value, like this:
Copy code
override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        return Mono.deferContextual {
            if (it.hasKey(MYID)) {
                MDC.putCloseable(MYID, it.get(MYID))
            }
            chain.filter(exchange)
        }
    }
The @RestControntroller functions are all suspended, and we are running netty (so full webflux). In the
async
code I have also added the MDCContext(), to make sure the MDC values are passed in. Is this a good solution? Are there any other pitfalls I need to be aware of? Or does anyone have a better implementation for this scenario
j
Consider using CoWebFilter
j
good idea, thanks!
k
As an aside, calling
putCloseable
without taking its return value is of no more use than a plain
put
.
j
yeah, get your point. its of no real use in this way, might as well use put
not sure what I am doing wrong here, but the MDC value is not available in the controller:
Copy code
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
class MyMdcFilter : CoWebFilter() {
    override suspend fun filter(exchange: ServerWebExchange, chain: CoWebFilterChain) =
        withContext(MDCContext()) {
            this.coroutineContext[ReactorContext]?.context?.let {
                if (it.hasKey(MYID)) {
                    MDC.put(
                        MYID, it.get(MYID)
                    )
                }
            }

            chain.filter(exchange)
        }
}
I can see that the MDC is populated, but is empty by the time the @RestController function is called
k
Could it be that the controller is running in a different thread? Each thread has its own separate MDC.
j
yeah you are most likely correct. not sure how to fix this really
b
The filters run on a different context than the controllers. It isn't really possible to fix in the annotation controllers. You can kind of fix it in the functional controllers by just running the same filter before the controllers are called in the router. Hopefully this is fixed in the next version of spring. https://kotlinlang.slack.com/archives/C0B8ZTWE4/p1694083089231459
j
thanks for the info, very helpful. I am trying to solve it using
withLoggingContext
in the context of the controller function
466 Views