Skip to content

Commit e7b9b8b

Browse files
authored
Request scope propagation for non-async calls in FT (helidon-io#2495)
* New test for issue 2480. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Swithed to new test framework for MP. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Use a wrapped supplier to propagate request scope even for synchronous calls as some FT primitives (like Retry) use executors and may run code in a different thread. Updated new test that fails without this change and passes with it. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Renamed variable. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Fixed copyright problems. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Dropped fixed port in config. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com> * Remove redundant main class. Signed-off-by: Santiago Pericasgeertsen <santiago.pericasgeertsen@oracle.com>
1 parent 7425747 commit e7b9b8b

15 files changed

Lines changed: 410 additions & 6 deletions

File tree

microprofile/fault-tolerance/src/main/java/io/helidon/microprofile/faulttolerance/MethodInvoker.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,11 +577,11 @@ Supplier<? extends CompletionStage<Object>> toCompletionStageSupplier(FtSupplier
577577
return () -> {
578578
invocationStartNanos = System.nanoTime();
579579

580+
// Wrap supplier with request context setup
581+
FtSupplier wrappedSupplier = requestContextSupplier(supplier);
582+
580583
CompletableFuture<Object> resultFuture = new CompletableFuture<>();
581584
if (introspector.isAsynchronous()) {
582-
// Wrap supplier with request context setup
583-
FtSupplier wrappedSupplier = requestContextSupplier(supplier);
584-
585585
// Invoke supplier in new thread and propagate ccl for config
586586
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
587587
Single<Object> single = Async.create().invoke(() -> {
@@ -634,7 +634,7 @@ Supplier<? extends CompletionStage<Object>> toCompletionStageSupplier(FtSupplier
634634
});
635635
} else {
636636
try {
637-
resultFuture.complete(supplier.get());
637+
resultFuture.complete(wrappedSupplier.get());
638638
return resultFuture;
639639
} catch (Throwable t) {
640640
resultFuture.completeExceptionally(t);

tests/functional/context-propagation/src/main/java/io/helidon/tests/functional/context/hello/HelloBean.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public String getHello() {
5252
}
5353

5454
/**
55-
* Runs in Hystrix thread.
55+
* Runs in FT thread.
5656
*
5757
* @return Hello string.
5858
*/
@@ -68,7 +68,7 @@ public String getHelloTimeout() {
6868
}
6969

7070
/**
71-
* Runs in Hystrix thread via FT async thread.
71+
* Runs via FT async thread.
7272
*
7373
* @return Hello string.
7474
*/

tests/functional/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@
4040
<module>context-propagation</module>
4141
<module>mp-synthetic-app</module>
4242
<module>mp-compression</module>
43+
<module>request-scope</module>
4344
</modules>
4445
</project>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright (c) 2020 Oracle and/or its affiliates.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
<parent>
23+
<artifactId>helidon-tests-functional-project</artifactId>
24+
<groupId>io.helidon.tests.functional</groupId>
25+
<version>2.1.1-SNAPSHOT</version>
26+
</parent>
27+
28+
<artifactId>helidon-tests-functional-request-scope</artifactId>
29+
<name>Helidon Functional Test: Request Scope and Fault Tolerance</name>
30+
31+
<dependencies>
32+
<dependency>
33+
<groupId>io.helidon.microprofile.bundles</groupId>
34+
<artifactId>helidon-microprofile-core</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>io.helidon.config</groupId>
38+
<artifactId>helidon-config-yaml</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>io.helidon.microprofile</groupId>
42+
<artifactId>helidon-microprofile-fault-tolerance</artifactId>
43+
</dependency>
44+
<dependency>
45+
<groupId>io.helidon.microprofile.metrics</groupId>
46+
<artifactId>helidon-microprofile-metrics</artifactId>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.junit.jupiter</groupId>
50+
<artifactId>junit-jupiter-api</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>org.hamcrest</groupId>
55+
<artifactId>hamcrest-all</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
<dependency>
59+
<groupId>org.junit.jupiter</groupId>
60+
<artifactId>junit-jupiter-params</artifactId>
61+
<scope>test</scope>
62+
</dependency>
63+
<dependency>
64+
<groupId>io.helidon.microprofile.tests</groupId>
65+
<artifactId>helidon-microprofile-tests-junit5</artifactId>
66+
<scope>test</scope>
67+
</dependency>
68+
</dependencies>
69+
</project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
public class IllegalTenantException extends Exception {
19+
20+
public IllegalTenantException(String message) {
21+
super(message);
22+
}
23+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
import javax.enterprise.context.RequestScoped;
19+
import javax.inject.Inject;
20+
import javax.ws.rs.GET;
21+
import javax.ws.rs.Path;
22+
import javax.ws.rs.WebApplicationException;
23+
import javax.ws.rs.core.Response;
24+
25+
@RequestScoped
26+
@Path("/test")
27+
public class MultiTenantService {
28+
29+
@Inject
30+
SomeService someService;
31+
32+
@GET
33+
public String getTenantResource() {
34+
try {
35+
return someService.test();
36+
} catch (IllegalTenantException e) {
37+
return "Expected";
38+
} catch (Exception e) {
39+
// This path implies a CDI exception related to request scope
40+
// See https://github.com/oracle/helidon/issues/2480
41+
throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
42+
}
43+
}
44+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
import javax.enterprise.context.RequestScoped;
19+
import javax.inject.Inject;
20+
21+
@RequestScoped
22+
@TestQualifier
23+
public class RequestTestQualifier {
24+
25+
@Inject
26+
TenantContext tenantContext;
27+
28+
public String test() throws Exception {
29+
String tenantId = tenantContext.getTenantId();
30+
System.out.println("Tenant Context: " + tenantId);
31+
if (tenantId == null) {
32+
throw new IllegalTenantException("No tenant context");
33+
}
34+
return tenantId;
35+
}
36+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
import javax.enterprise.context.ApplicationScoped;
19+
import javax.inject.Inject;
20+
21+
import org.eclipse.microprofile.faulttolerance.Retry;
22+
23+
@ApplicationScoped
24+
public class SomeService {
25+
26+
@Inject
27+
@TestQualifier
28+
RequestTestQualifier requestTestQualifier;
29+
30+
@Retry
31+
public String test() throws Exception {
32+
return requestTestQualifier.test();
33+
}
34+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
import javax.enterprise.context.RequestScoped;
19+
import javax.ws.rs.core.Context;
20+
21+
import io.helidon.webserver.ServerRequest;
22+
23+
@RequestScoped
24+
public class TenantContext {
25+
26+
@Context
27+
private ServerRequest request;
28+
29+
public String getTenantId() {
30+
return request.headers().value("x-tenant-id").orElse(null);
31+
}
32+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tests.functional.requestscope;
17+
18+
import javax.inject.Qualifier;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.Target;
21+
22+
import static java.lang.annotation.ElementType.FIELD;
23+
import static java.lang.annotation.ElementType.METHOD;
24+
import static java.lang.annotation.ElementType.PARAMETER;
25+
import static java.lang.annotation.ElementType.TYPE;
26+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
27+
28+
@Qualifier
29+
@Retention(RUNTIME)
30+
@Target({TYPE, METHOD, FIELD, PARAMETER})
31+
public @interface TestQualifier {
32+
}

0 commit comments

Comments
 (0)