Skip to content

Commit 2a378ec

Browse files
authored
Support for injection of ServerRequest and ServerResponse also via CDI. New functional test to verify both types of injection. (helidon-io#6798)
1 parent 8fcf110 commit 2a378ec

9 files changed

Lines changed: 275 additions & 1 deletion

File tree

microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
import io.helidon.microprofile.cdi.RuntimeStart;
4949
import io.helidon.webserver.KeyPerformanceIndicatorSupport;
5050
import io.helidon.webserver.Routing;
51+
import io.helidon.webserver.ServerRequest;
52+
import io.helidon.webserver.ServerResponse;
5153
import io.helidon.webserver.Service;
5254
import io.helidon.webserver.WebServer;
5355
import io.helidon.webserver.jersey.JerseySupport;
@@ -57,8 +59,13 @@
5759
import jakarta.enterprise.context.ApplicationScoped;
5860
import jakarta.enterprise.context.BeforeDestroyed;
5961
import jakarta.enterprise.context.Initialized;
62+
import jakarta.enterprise.context.RequestScoped;
6063
import jakarta.enterprise.context.spi.CreationalContext;
6164
import jakarta.enterprise.event.Observes;
65+
import jakarta.enterprise.inject.Any;
66+
import jakarta.enterprise.inject.CreationException;
67+
import jakarta.enterprise.inject.Default;
68+
import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
6269
import jakarta.enterprise.inject.spi.Bean;
6370
import jakarta.enterprise.inject.spi.BeanManager;
6471
import jakarta.enterprise.inject.spi.CDI;
@@ -224,6 +231,27 @@ private void startServer(@Observes @Priority(PLATFORM_AFTER + 100) @Initialized(
224231
STARTUP_LOGGER.finest("Server created");
225232
}
226233

234+
/**
235+
* Make {@code ServerRequest} and {@code ServerResponse} available for injection
236+
* via CDI by registering them as beans.
237+
*
238+
* @param event after bean discovery event
239+
*/
240+
private void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {
241+
event.addBean()
242+
.qualifiers(Set.of(Default.Literal.INSTANCE, Any.Literal.INSTANCE))
243+
.addTransitiveTypeClosure(ServerRequest.class)
244+
.scope(RequestScoped.class)
245+
.createWith(cc -> Contexts.context().flatMap(c -> c.get(ServerRequest.class))
246+
.orElseThrow(() -> new CreationException("Unable to retrieve ServerRequest from context")));
247+
event.addBean()
248+
.qualifiers(Set.of(Default.Literal.INSTANCE, Any.Literal.INSTANCE))
249+
.addTransitiveTypeClosure(ServerResponse.class)
250+
.scope(RequestScoped.class)
251+
.createWith(cc -> Contexts.context().flatMap(c -> c.get(ServerResponse.class))
252+
.orElseThrow(() -> new CreationException("Unable to retrieve ServerResponse from context")));
253+
}
254+
227255
private void registerJaxRsApplications(BeanManager beanManager) {
228256
JaxRsCdiExtension jaxRs = beanManager.getExtension(JaxRsCdiExtension.class);
229257

tests/functional/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
<module>mp-compression</module>
4343
<module>request-scope</module>
4444
<module>request-scope-cdi</module>
45+
<module>request-scope-injection</module>
4546
<module>jax-rs-multiple-apps</module>
4647
<module>param-converter-provider</module>
4748
<module>config-profiles</module>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright (c) 2023 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 https://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>3.2.1-SNAPSHOT</version>
26+
</parent>
27+
28+
<artifactId>helidon-tests-functional-request-scope-injection</artifactId>
29+
<name>Helidon Functional Test: Helidon Request Scope Injection</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.tests</groupId>
42+
<artifactId>helidon-microprofile-tests-junit5</artifactId>
43+
<scope>test</scope>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.junit.jupiter</groupId>
47+
<artifactId>junit-jupiter-api</artifactId>
48+
<scope>test</scope>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.hamcrest</groupId>
52+
<artifactId>hamcrest-all</artifactId>
53+
<scope>test</scope>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.junit.jupiter</groupId>
57+
<artifactId>junit-jupiter-params</artifactId>
58+
<scope>test</scope>
59+
</dependency>
60+
</dependencies>
61+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2023 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+
17+
package io.helidon.tests.functional.context.injection;
18+
19+
import java.util.Objects;
20+
21+
import io.helidon.webserver.ServerRequest;
22+
import io.helidon.webserver.ServerResponse;
23+
import jakarta.inject.Inject;
24+
import jakarta.ws.rs.GET;
25+
import jakarta.ws.rs.Path;
26+
import jakarta.ws.rs.core.Context;
27+
import jakarta.ws.rs.core.Response;
28+
29+
/**
30+
* Verifies that {@code ServerRequest} and {@code ServerResponse} are injectable
31+
* both via {@code @Context} and {@code @Inject}.
32+
*/
33+
@Path("/check")
34+
public class CheckInjectionResource {
35+
36+
@Context
37+
private ServerRequest serverRequest;
38+
39+
@Context
40+
private ServerResponse serverResponse;
41+
42+
@Inject
43+
private ServerRequest serverRequestCdi;
44+
45+
@Inject
46+
private ServerResponse serverResponseCdi;
47+
48+
@GET
49+
public Response checkInjection() {
50+
Objects.requireNonNull(serverRequest);
51+
Objects.requireNonNull(serverResponse);
52+
Objects.requireNonNull(serverRequestCdi);
53+
Objects.requireNonNull(serverResponseCdi);
54+
if (!serverRequestCdi.path().equals(serverRequest.path())
55+
|| !serverResponseCdi.status().equals(serverResponse.status())) {
56+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
57+
}
58+
return Response.ok().build();
59+
}
60+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2023 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+
17+
/**
18+
* Simple app to verify injection of {@code ServerRequest} and {@code ServerResponse}.
19+
*/
20+
package io.helidon.tests.functional.context.injection;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright (c) 2023 Oracle and/or its affiliates.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
22+
https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
23+
version="3.0"
24+
bean-discovery-mode="annotated">
25+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2023 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+
17+
package io.helidon.tests.functional.context.injection;
18+
19+
import io.helidon.microprofile.tests.junit5.HelidonTest;
20+
import jakarta.inject.Inject;
21+
import jakarta.ws.rs.client.WebTarget;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.hamcrest.CoreMatchers.is;
25+
import static org.hamcrest.MatcherAssert.assertThat;
26+
27+
/**
28+
* Unit test for {@link CheckInjectionResource}.
29+
*/
30+
@HelidonTest
31+
class CheckInjectionTest {
32+
33+
private final WebTarget baseTarget;
34+
35+
@Inject
36+
CheckInjectionTest(WebTarget baseTarget) {
37+
this.baseTarget = baseTarget;
38+
}
39+
40+
@Test
41+
void testCheckInjection() {
42+
WebTarget target = baseTarget.path("/check");
43+
assertThat(target.request().get().getStatus(), is(200));
44+
}
45+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# Copyright (c) 2023 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+
17+
# Example Logging Configuration File
18+
# For more information see $JAVA_HOME/jre/lib/logging.properties
19+
20+
# Send messages to the console
21+
handlers=io.helidon.common.HelidonConsoleHandler
22+
23+
# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
24+
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
25+
26+
# Global logging level. Can be overridden by specific loggers
27+
.level=INFO
28+
29+
# Component specific log levels
30+
AUDIT.level=FINEST

webserver/jersey/src/main/java/io/helidon/webserver/jersey/JerseySupport.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2022 Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2023 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -275,6 +275,10 @@ public void accept(ServerRequest req, ServerResponse res) {
275275
.orElseThrow(() -> new IllegalStateException("Context must be propagated from server"));
276276
Context jerseyContext = Context.create(parent);
277277

278+
// make these available in context for ServerCdiExtension
279+
jerseyContext.supply(ServerRequest.class, () -> req);
280+
jerseyContext.supply(ServerResponse.class, () -> res);
281+
278282
Contexts.runInContext(jerseyContext, () -> doAccept(req, res));
279283
}
280284

0 commit comments

Comments
 (0)