Share data through a request lifecycle in Spring Webflux

Viewed 1062

In Spring MVC I can use ThreadLocal to share data between different components through a request, and the data will be automatically cleared when the request is fulfilled. With WebFlux, since a request can be handled by multiple threads, this solution will not work. How to implement a similar solution so that initially a WebFilter can set some data in the request context, then the data can be accessed and modified in the controllers, and any event handlers that the request has gone through?

I tried subscriberContext but it did not work. Here is my code. Why this does not work? Is there another way to share the data?

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    exchange.getResponse().beforeCommit(() -> {
        return Mono.subscriberContext()
         .map(context -> {
              context.hasKey("test"); // this returns false
         })
    }

    return Mono.subscriberContext()
        .map(context -> {context.put("test", "test");})
        .flatMap(chain.filter(exchange))
}
1 Answers

If I am not mistaken, it is because of .beforeCommit(). This Mono and the filter Mono do not share the same Subscriber.

To add the value, to the subscriberContext of the request. Try this:

chain.filter(exchange)
  .subscriberContext(context -> context.put("KEY", "VALUE"));

You can also share values in ServerWebExchange attributes. This is Spring Web Flux not Reactor though. For example:

exchange.getAttributes().put("KEY", "VALUE");

Now, anywhere in your application where you have access to ServerWebExchange you can access the attribute using

exchange.getAttributes().get("KEY");
Related