Search code examples
javareactive-programmingspring-webflux

Why is reactor context throwing "Context does not contain key" when .block() is called?


I have a WebFilter that injects a context

public class MyWebFilter implements WebFilter {
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(exchange)
      .contextWrite(ctx -> ctx.put("context", "some-context"));
  }
}

In my Controller, I can read it and return it successfully

@RestController
public class MyController {
  @GetMapping(path = "test")
  public Mono<String> test() {
    return Mono.deferContextual(ctx -> Mono.just(ctx.get("context")));
  }
}

However, if I call .block() on it:

Mono.deferContextual(ctx -> Mono.just(ctx.get("context"))).block();

it throws this exception

java.util.NoSuchElementException: Context does not contain key: context

I'm having trouble wrapping my head around the order of execution in the reactive world.


Solution

  • When you call .block(), that line is subscribed to and evaluated immediately, without any connection to the context provided in the outer chain. When you return without .block, it becomes part of the larger chain which has the context, and isn't evaluated until something subscribes to the outer chain at which time the context is available.