Skip to content

Commit 8219743

Browse files
authored
4.x: Support Jersey on Helidon SE WebServer (helidon-io#9985)
* Support Jersey on Helidon SE WebServer * Javadoc fix, as Jakarta inject now has module-info * Comment update to align with new module location
1 parent c9aa9bc commit 8219743

24 files changed

Lines changed: 413 additions & 69 deletions

File tree

all/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@
5757
<groupId>io.helidon.jersey</groupId>
5858
<artifactId>helidon-jersey-media-jsonp</artifactId>
5959
</dependency>
60+
<dependency>
61+
<groupId>io.helidon.jersey</groupId>
62+
<artifactId>helidon-jersey-webserver</artifactId>
63+
</dependency>
6064
<dependency>
6165
<groupId>io.helidon.graphql</groupId>
6266
<artifactId>helidon-graphql-server</artifactId>

bom/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@
7878
<artifactId>helidon-jersey-media-jsonp</artifactId>
7979
<version>${helidon.version}</version>
8080
</dependency>
81+
<dependency>
82+
<groupId>io.helidon.jersey</groupId>
83+
<artifactId>helidon-jersey-webserver</artifactId>
84+
<version>${helidon.version}</version>
85+
</dependency>
8186
<!-- graphQL -->
8287
<dependency>
8388
<groupId>io.helidon.graphql</groupId>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module:jakarta.inject
2+
jakarta.inject

etc/javadoc/jakarta-inject/package-list

Lines changed: 0 additions & 1 deletion
This file was deleted.

jersey/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<module>server</module>
4242
<module>jsonp</module>
4343
<module>common</module>
44+
<module>webserver</module>
4445
</modules>
4546

4647
<profiles>

jersey/webserver/pom.xml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright (c) 2025 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+
<groupId>io.helidon.jersey</groupId>
24+
<artifactId>helidon-jersey-project</artifactId>
25+
<version>4.2.0-SNAPSHOT</version>
26+
</parent>
27+
28+
<artifactId>helidon-jersey-webserver</artifactId>
29+
<name>Helidon Jersey WebServer</name>
30+
<description>Adds support for running Jersey on top of Helidon WebServer (without CDI)</description>
31+
32+
<properties>
33+
<javadoc.fail-on-warnings>true</javadoc.fail-on-warnings>
34+
</properties>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>io.helidon.common</groupId>
39+
<artifactId>helidon-common</artifactId>
40+
</dependency>
41+
<dependency>
42+
<groupId>io.helidon.common</groupId>
43+
<artifactId>helidon-common-socket</artifactId>
44+
</dependency>
45+
<dependency>
46+
<groupId>io.helidon.common</groupId>
47+
<artifactId>helidon-common-uri</artifactId>
48+
</dependency>
49+
<dependency>
50+
<groupId>io.helidon.common</groupId>
51+
<artifactId>helidon-common-context</artifactId>
52+
</dependency>
53+
<dependency>
54+
<groupId>io.helidon.common</groupId>
55+
<artifactId>helidon-common-config</artifactId>
56+
</dependency>
57+
<dependency>
58+
<groupId>io.helidon.http</groupId>
59+
<artifactId>helidon-http</artifactId>
60+
</dependency>
61+
<dependency>
62+
<groupId>io.helidon.http.media</groupId>
63+
<artifactId>helidon-http-media</artifactId>
64+
</dependency>
65+
<dependency>
66+
<groupId>jakarta.inject</groupId>
67+
<artifactId>jakarta.inject-api</artifactId>
68+
</dependency>
69+
<dependency>
70+
<groupId>io.helidon.webserver</groupId>
71+
<artifactId>helidon-webserver</artifactId>
72+
</dependency>
73+
<dependency>
74+
<groupId>org.glassfish.jersey.core</groupId>
75+
<artifactId>jersey-common</artifactId>
76+
</dependency>
77+
<dependency>
78+
<groupId>org.glassfish.jersey.core</groupId>
79+
<artifactId>jersey-server</artifactId>
80+
</dependency>
81+
<dependency>
82+
<groupId>io.helidon.jersey</groupId>
83+
<artifactId>helidon-jersey-server</artifactId>
84+
</dependency>
85+
<dependency>
86+
<groupId>jakarta.ws.rs</groupId>
87+
<artifactId>jakarta.ws.rs-api</artifactId>
88+
</dependency>
89+
<dependency>
90+
<groupId>io.helidon.webserver.testing.junit5</groupId>
91+
<artifactId>helidon-webserver-testing-junit5</artifactId>
92+
<scope>test</scope>
93+
</dependency>
94+
<dependency>
95+
<groupId>io.helidon.logging</groupId>
96+
<artifactId>helidon-logging-jul</artifactId>
97+
<scope>test</scope>
98+
</dependency>
99+
<dependency>
100+
<groupId>org.hamcrest</groupId>
101+
<artifactId>hamcrest-all</artifactId>
102+
<scope>test</scope>
103+
</dependency>
104+
<dependency>
105+
<groupId>org.junit.jupiter</groupId>
106+
<artifactId>junit-jupiter-api</artifactId>
107+
<scope>test</scope>
108+
</dependency>
109+
</dependencies>
110+
111+
</project>

microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java renamed to jersey/webserver/src/main/java/io/helidon/jersey/webserver/JaxRsService.java

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.microprofile.server;
17+
package io.helidon.jersey.webserver;
1818

1919
import java.io.IOException;
2020
import java.io.OutputStream;
@@ -26,13 +26,15 @@
2626
import java.util.Collections;
2727
import java.util.List;
2828
import java.util.Map;
29+
import java.util.Objects;
2930
import java.util.Optional;
3031
import java.util.Set;
3132
import java.util.WeakHashMap;
3233
import java.util.concurrent.CountDownLatch;
3334
import java.util.concurrent.TimeUnit;
3435
import java.util.function.Supplier;
3536

37+
import io.helidon.common.config.Config;
3638
import io.helidon.common.context.Context;
3739
import io.helidon.common.context.Contexts;
3840
import io.helidon.common.uri.UriInfo;
@@ -43,7 +45,6 @@
4345
import io.helidon.http.InternalServerException;
4446
import io.helidon.http.ServerResponseHeaders;
4547
import io.helidon.http.Status;
46-
import io.helidon.microprofile.server.HelidonHK2InjectionManagerFactory.InjectionManagerWrapper;
4748
import io.helidon.webserver.KeyPerformanceIndicatorSupport;
4849
import io.helidon.webserver.http.HttpRules;
4950
import io.helidon.webserver.http.HttpService;
@@ -56,8 +57,6 @@
5657
import jakarta.ws.rs.core.GenericType;
5758
import jakarta.ws.rs.core.Response;
5859
import jakarta.ws.rs.core.SecurityContext;
59-
import org.eclipse.microprofile.config.Config;
60-
import org.eclipse.microprofile.config.ConfigProvider;
6160
import org.glassfish.jersey.CommonProperties;
6261
import org.glassfish.jersey.internal.MapPropertiesDelegate;
6362
import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -71,7 +70,10 @@
7170
import org.glassfish.jersey.server.spi.Container;
7271
import org.glassfish.jersey.server.spi.ContainerResponseWriter;
7372

74-
class JaxRsService implements HttpService {
73+
/**
74+
* WebServer {@link io.helidon.webserver.http.HttpService} that adds support for a JAX-RS application.
75+
*/
76+
public class JaxRsService implements HttpService {
7577
/**
7678
* If set to {@code "true"}, Jersey will ignore responses in exceptions.
7779
*/
@@ -97,26 +99,87 @@ private JaxRsService(ResourceConfig resourceConfig,
9799
this.application = getApplication(resourceConfig);
98100
}
99101

100-
static JaxRsService create(ResourceConfig resourceConfig, InjectionManager injectionManager) {
102+
/**
103+
* Create a new JAX-RS integration service with the default injection manager.
104+
*
105+
* @param config configuration, used to configure Jersey
106+
* @param resourceConfig containing application resources
107+
* @return a new service to register with the WebServer
108+
*/
109+
public static JaxRsService create(Config config,
110+
ResourceConfig resourceConfig) {
111+
Objects.requireNonNull(config);
112+
Objects.requireNonNull(resourceConfig);
113+
114+
return doCreate(config, resourceConfig, null);
115+
}
116+
117+
/**
118+
* Create a new JAX-RS integration service with a custom injection manager.
119+
*
120+
* @param config configuration, used to configure Jersey
121+
* @param resourceConfig containing application resources
122+
* @param injectionManager injection manager to use
123+
* @return a new service to register with the WebServer
124+
* @see #create(io.helidon.common.config.Config, org.glassfish.jersey.server.ResourceConfig)
125+
*/
126+
public static JaxRsService create(Config config,
127+
ResourceConfig resourceConfig,
128+
InjectionManager injectionManager) {
129+
Objects.requireNonNull(config);
130+
Objects.requireNonNull(resourceConfig);
131+
Objects.requireNonNull(injectionManager);
132+
133+
return doCreate(config, resourceConfig, injectionManager);
134+
}
135+
136+
@Override
137+
public void routing(HttpRules rules) {
138+
rules.any(this::handle);
139+
}
140+
141+
@Override
142+
public void beforeStart() {
143+
appHandler.onStartup(container);
144+
INJECTION_MANAGERS.add(appHandler.getInjectionManager());
145+
}
146+
147+
@Override
148+
public void afterStop() {
149+
try {
150+
InjectionManager ij = appHandler.getInjectionManager();
151+
if (INJECTION_MANAGERS.remove(ij)) {
152+
appHandler.onShutdown(container);
153+
}
154+
} catch (Exception e) {
155+
if (LOGGER.isLoggable(Level.DEBUG)) {
156+
LOGGER.log(Level.DEBUG, "Exception during shutdown of Jersey", e);
157+
}
158+
LOGGER.log(Level.WARNING, "Exception while shutting down Jersey's application handler " + e.getMessage());
159+
}
160+
}
101161

102-
Config config = ConfigProvider.getConfig();
162+
private static JaxRsService doCreate(Config config,
163+
ResourceConfig resourceConfig,
164+
InjectionManager injectionManager) {
103165

104166
// Silence warnings from Jersey by disabling the default data source provider. See 9019.
105167
// To pass TCK we support a system property to control whether or not we disable the default provider
106168
// We also support the property via MicroProfile config in case a user wants to control the property.
107-
boolean disableDatasourceProvider = config.getOptionalValue(DISABLE_DATASOURCE_PROVIDER, Boolean.class)
169+
boolean disableDatasourceProvider = config.get(DISABLE_DATASOURCE_PROVIDER)
170+
.asBoolean()
108171
.orElseGet(() -> Boolean.parseBoolean(System.getProperty(DISABLE_DATASOURCE_PROVIDER, "true")));
172+
109173
if (!resourceConfig.hasProperty(CommonProperties.PROVIDER_DEFAULT_DISABLE) && disableDatasourceProvider) {
110174
resourceConfig.addProperties(Map.of(CommonProperties.PROVIDER_DEFAULT_DISABLE, "DATASOURCE"));
111175
}
112176
if (!resourceConfig.hasProperty(ServerProperties.WADL_FEATURE_DISABLE)) {
113177
resourceConfig.addProperties(Map.of(ServerProperties.WADL_FEATURE_DISABLE, "true"));
114178
}
115179

116-
InjectionManager ij = injectionManager == null ? null : new InjectionManagerWrapper(injectionManager, resourceConfig);
117180
ApplicationHandler appHandler = new ApplicationHandler(resourceConfig,
118181
new WebServerBinder(),
119-
ij);
182+
injectionManager);
120183
Container container = new HelidonJerseyContainer(appHandler);
121184

122185
// This configuration via system properties is for the Jersey Client API. Any
@@ -125,7 +188,7 @@ static JaxRsService create(ResourceConfig resourceConfig, InjectionManager injec
125188
// See https://github.com/eclipse-ee4j/jersey/pull/4641.
126189
if (!System.getProperties().contains(IGNORE_EXCEPTION_RESPONSE)) {
127190
System.setProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, "true");
128-
String ignore = config.getOptionalValue(IGNORE_EXCEPTION_RESPONSE, String.class).orElse("true");
191+
String ignore = config.get(IGNORE_EXCEPTION_RESPONSE).asString().orElse("true");
129192
System.setProperty(IGNORE_EXCEPTION_RESPONSE, ignore);
130193
}
131194

@@ -146,32 +209,6 @@ private static String basePath(UriPath path) {
146209
}
147210
}
148211

149-
@Override
150-
public void routing(HttpRules rules) {
151-
rules.any(this::handle);
152-
}
153-
154-
@Override
155-
public void beforeStart() {
156-
appHandler.onStartup(container);
157-
INJECTION_MANAGERS.add(appHandler.getInjectionManager());
158-
}
159-
160-
@Override
161-
public void afterStop() {
162-
try {
163-
InjectionManager ij = appHandler.getInjectionManager();
164-
if (INJECTION_MANAGERS.remove(ij)) {
165-
appHandler.onShutdown(container);
166-
}
167-
} catch (Exception e) {
168-
if (LOGGER.isLoggable(Level.DEBUG)) {
169-
LOGGER.log(Level.DEBUG, "Exception during shutdown of Jersey", e);
170-
}
171-
LOGGER.log(Level.WARNING, "Exception while shutting down Jersey's application handler " + e.getMessage());
172-
}
173-
}
174-
175212
/**
176213
* Extracts the actual {@code Application} instance.
177214
*
@@ -202,7 +239,7 @@ private void handle(ServerRequest req, ServerResponse res) {
202239
}
203240

204241
private void doHandle(Context ctx, ServerRequest req, ServerResponse res) {
205-
// save headers in case MP request processing fails
242+
// save headers in case JAX-RS request processing fails
206243
ServerResponseHeaders savedResponseHeaders = null;
207244
if (req.listenerContext().config().restoreResponseHeaders()) {
208245
savedResponseHeaders = ServerResponseHeaders.create(res.headers());

microprofile/server/src/main/java/io/helidon/microprofile/server/LazyInputStream.java renamed to jersey/webserver/src/main/java/io/helidon/jersey/webserver/LazyInputStream.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 Oracle and/or its affiliates.
2+
* Copyright (c) 2024, 2025 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.
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.microprofile.server;
17+
package io.helidon.jersey.webserver;
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;

microprofile/server/src/main/java/io/helidon/microprofile/server/WebServerBinder.java renamed to jersey/webserver/src/main/java/io/helidon/jersey/webserver/WebServerBinder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2025 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.
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.helidon.microprofile.server;
17+
package io.helidon.jersey.webserver;
1818

1919
import io.helidon.webserver.http.ServerRequest;
2020
import io.helidon.webserver.http.ServerResponse;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2025 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+
* Jersey integration with Helidon WebServer.
19+
*/
20+
package io.helidon.jersey.webserver;

0 commit comments

Comments
 (0)