Reactive RESTEasy and Hibernate Panache: Does request‑scoped context survive worker offload?
0 reputation · 26 Aug 2023, 14:19 UTC
0 reputation · 26 Aug 2023, 14:19 UTC
Goal: Ensure that request‑scoped data such as the current security principal or MDC context is available inside a Hibernate Panache repository method when it is invoked from a reactive RESTEasy resource that returns a Uni or Multi.
Current behavior: Quarkus automatically off‑loads the blocking Panache call to a worker thread, but it does not propagate @RequestScoped beans or Vert.x thread‑local storage to that thread, so the repository method sees a null or default security identity and any MDC values are lost.
31775 reputation · 26 Aug 2023, 16:49 UTC
No — not by default. When a reactive RESTEasy resource returns a Uni or Multi and Quarkus off-loads a blocking Hibernate Panache call to a worker thread, the CDI request context and Vert.x thread-local data do not automatically travel with it. The repository method will typically see an inactive request context (or a default/null security identity) and MDC values set on the event-loop thread are lost. The standard fix is the SmallRye Context Propagation extension, which is designed exactly for this boundary.
Established behavior (well-documented Quarkus design):
quarkus-smallrye-context-propagation extension. With it on the classpath, context is captured when a Uni/Multi pipeline is assembled and restored around each stage, including stages that execute on worker threads.Assumptions to verify in your setup:
./mvnw quarkus:add-extension -Dextensions="smallrye-context-propagation"Uni pipeline rather than before it, so the captured context is restored when the stage executes:@GET
public Uni<List<Item>> items() {
return Uni.createFrom().item(() -> itemRepo.findForCurrentUser());
}SecurityIdentity principal and an MDC key inside the repository method. With the extension present they should match the values set during request processing; temporarily removing the extension should show them missing — a quick A/B check that confirms propagation is what fixed it.There is no separate switch to make raw Vert.x thread-local storage flow with Uni/Multi continuations; the context-propagation extension is the mechanism Quarkus provides, and it covers CDI scopes plus MDC. Manual capture-and-restore (reading the principal/MDC on the request thread, closing over the values, and re-applying them in the blocking stage) works but is fragile: it is easy to miss a path, and it leaks request data if you forget to clear it on the worker thread. Treat it as a fallback, not a pattern.
One detail would change this recommendation: are you on blocking Panache (this answer applies) or Hibernate Reactive Panache (no off-load, different context rules)? Also confirm your Quarkus version, since propagation defaults have evolved across releases.
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 27 Aug 2023, 02:17 UTC
Quarkus 2.7+ introduces the configuration property quarkus.resteasy-reactive.propagate-request-context. When set to true, the reactive request context – including any @RequestScoped CDI beans, Vert.x thread‑local data, and MDC values – is captured on the event-loop thread and restored around the worker-thread execution of a @Blocking call (e.g., a Hibernate Panache repository method). This eliminates the need for the SmallRye Context Propagation extension or manual Vertx.currentContext().runOnContext tricks for the common case of blocking Panache calls.
false, the worker thread receives a fresh Vert.x context, so request‑scoped beans resolve to their default proxies (often null) and MDC is lost.