Skip to content

Commit f98b6ef

Browse files
authored
Merge pull request #49163 from FroMage/49133
[3.20] Make sure we propagate context locals from REST server to clients
2 parents b6acfcf + 37b5236 commit f98b6ef

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/ContextLocalPropagationTest.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import io.quarkus.test.QuarkusUnitTest;
2323
import io.smallrye.common.vertx.ContextLocals;
24+
import io.smallrye.mutiny.Uni;
2425
import io.vertx.core.Context;
2526
import io.vertx.core.Vertx;
2627

@@ -33,13 +34,21 @@ public class ContextLocalPropagationTest {
3334
"http://localhost:${quarkus.http.test-port:8081}");
3435

3536
@Test
36-
void testQueryParamsWithPrimitiveArrays() {
37+
void testClientFilterSeesParentContext() {
3738
when().get("test/invokeClient")
3839
.then()
3940
.statusCode(200)
4041
.body(is("test/foo/bar"));
4142
}
4243

44+
@Test
45+
void testClientUniInheritsParentContext() {
46+
when().get("test/client-inherits-context")
47+
.then()
48+
.statusCode(200)
49+
.body(is("test/set-in-parent"));
50+
}
51+
4352
@Path("test")
4453
public static class Resource {
4554

@@ -58,11 +67,25 @@ public String invokeClient() {
5867
return result + "/" + fromRequest.orElse("none") + "/" + fromResponse.orElse("none");
5968
}
6069

70+
@Path("client-inherits-context")
71+
@GET
72+
public Uni<String> clientInheritsContext() {
73+
ContextLocals.put("parent-value", "set-in-parent");
74+
return client.getUni()
75+
.map(result -> result + "/" + ContextLocals.get("parent-value").orElse("none"));
76+
}
77+
6178
@Path("toClient")
6279
@GET
6380
public String toClient() {
6481
return "test";
6582
}
83+
84+
@Path("toClient2")
85+
@GET
86+
public String toClient2() {
87+
return "test";
88+
}
6689
}
6790

6891
@Path("test")
@@ -74,6 +97,10 @@ public interface Client {
7497
@GET
7598
@Path("toClient")
7699
String get();
100+
101+
@GET
102+
@Path("toClient2")
103+
Uni<String> getUni();
77104
}
78105

79106
public static class RequestFilter implements ClientRequestFilter {
@@ -110,10 +137,10 @@ private static Context determineRestClientContext() {
110137
// We will need a proper solution soon, but as we need to have a proper way to
111138
// set contextual information in Quarkus 3.20 (LTS), we can't risk breaking
112139
// client code everywhere, so for now we will tell people to check the context
113-
Optional<Object> maybeParentContext = ContextLocals.get("__PARENT_CONTEXT__");
140+
var maybeParentContext = ContextLocals.getParentContext();
114141
Context effectiveContext;
115-
if (maybeParentContext.isPresent()) {
116-
effectiveContext = (Context) maybeParentContext.get();
142+
if (maybeParentContext != null) {
143+
effectiveContext = maybeParentContext;
117144
} else {
118145
effectiveContext = Vertx.currentContext();
119146
}

independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientRequestContextImpl.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,7 @@ public ClientRequestContextImpl(RestClientRequestContext restClientRequestContex
6565
// Always create a duplicated context because each REST Client invocation must have its own context
6666
// A separate context allows integrations like OTel to create a separate Span for each invocation (expected)
6767
Context current = client.vertx.getOrCreateContext();
68-
this.context = VertxContext.createNewDuplicatedContext(current);
69-
// If an interceptor wants to access the parent context, it can do so by using the "__PARENT_CONTEXT__" key.
70-
// This approach is compatible with the next-to-be nested context support (from SmallRye Common).
71-
// The "__PARENT_CONTEXT__" key will continue to reference the _parent_ context.
72-
// So, currently, an interceptor needing to read from the original context will need to use:
73-
// Context parent = ContextLocals.get("__PARENT_CONTEXT__");
74-
// V v = parent.getLocal("some-key");
75-
// To write to the original context, it will need to use:
76-
// Context parent = ContextLocals.get("__PARENT_CONTEXT__");
77-
// parent.putLocal("some-key", someValue);
78-
// Note that unlike with nested contexts, multiple child contexts can write to the same parent key, and may
79-
// lead to a race condition.
80-
this.context.putLocal("__PARENT_CONTEXT__", current);
68+
this.context = VertxContext.newNestedContext(current);
8169
restClientRequestContext.properties.put(VERTX_CONTEXT_PROPERTY, context);
8270
}
8371

0 commit comments

Comments
 (0)