Skip to content

Commit 85e6620

Browse files
jansupolsenivam
authored andcommitted
Backport compatibility of JacksonFeature with RestEasy to 2.x
Signed-off-by: jansupol <jan.supol@oracle.com>
1 parent d984198 commit 85e6620

File tree

5 files changed

+246
-13
lines changed

5 files changed

+246
-13
lines changed

media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -50,24 +50,33 @@
5050
public class DefaultJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
5151
private Configuration commonConfig;
5252
private static final Logger LOGGER = Logger.getLogger(DefaultJacksonJaxbJsonProvider.class.getName());
53+
private final boolean hasConfig;
5354

5455
@Inject
5556
public DefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
5657
this(providers, config, DEFAULT_ANNOTATIONS);
5758
}
5859

5960
//do not register JaxbAnnotationModule because it brakes default annotations processing
60-
private static final String EXCLUDE_MODULE_NAME = "JaxbAnnotationModule";
61+
private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"};
6162

6263
public DefaultJacksonJaxbJsonProvider(Providers providers, Configuration config, Annotations... annotationsToUse) {
6364
super(annotationsToUse);
6465
this.commonConfig = config;
6566
_providers = providers;
6667

67-
Object jaxrsFeatureBag = config.getProperty(JaxrsFeatureBag.JAXRS_FEATURE);
68-
if (jaxrsFeatureBag != null && (JaxrsFeatureBag.class.isInstance(jaxrsFeatureBag))) {
69-
((JaxrsFeatureBag) jaxrsFeatureBag).configureJaxrsFeatures(this);
68+
boolean ex = true;
69+
try {
70+
Object jaxrsFeatureBag = config.getProperty(JaxrsFeatureBag.JAXRS_FEATURE);
71+
if (jaxrsFeatureBag != null && (JaxrsFeatureBag.class.isInstance(jaxrsFeatureBag))) {
72+
((JaxrsFeatureBag) jaxrsFeatureBag).configureJaxrsFeatures(this);
73+
}
74+
} catch (RuntimeException e) {
75+
// ignore - not configured
76+
LOGGER.fine(LocalizationMessages.ERROR_CONFIGURING(e.getMessage()));
77+
ex = false;
7078
}
79+
hasConfig = ex;
7180
}
7281

7382
@Override
@@ -82,7 +91,9 @@ protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaTy
8291
@Override
8392
protected JsonEndpointConfig _configForReading(ObjectReader reader, Annotation[] annotations) {
8493
try {
85-
updateFactoryConstraints(reader.getFactory());
94+
if (hasConfig) {
95+
updateFactoryConstraints(reader.getFactory());
96+
}
8697
} catch (Throwable t) {
8798
// A Jackson 14 would throw NoSuchMethodError, ClassNotFoundException, NoClassDefFoundError or similar
8899
// that should have been ignored
@@ -97,7 +108,7 @@ private void findAndRegisterModules() {
97108
final ObjectMapper defaultMapper = _mapperConfig.getDefaultMapper();
98109
final ObjectMapper mapper = _mapperConfig.getConfiguredMapper();
99110

100-
final List<Module> modules = filterModules();
111+
final List<Module> modules = filterModules();
101112

102113
defaultMapper.registerModules(modules);
103114
if (mapper != null) {
@@ -122,8 +133,9 @@ private List<Module> filterModules() {
122133
LOGGER.warning(LocalizationMessages.ERROR_MODULES_NOT_LOADED(e.getMessage()));
123134
return Collections.emptyList();
124135
}
125-
126-
modules.removeIf(mod -> mod.getModuleName().contains(EXCLUDE_MODULE_NAME));
136+
for (String exludeModuleName : EXCLUDE_MODULE_NAMES) {
137+
modules.removeIf(mod -> mod.getModuleName().contains(exludeModuleName));
138+
}
127139

128140
if (enabledModules != null && !enabledModules.isEmpty()) {
129141
final List<String> enabledModulesList = Arrays.asList(enabledModules.split(","));
@@ -161,4 +173,4 @@ private void updateFactoryConstraints(JsonFactory jsonFactory) {
161173
jsonFactory.setStreamReadConstraints(builder.build());
162174
}
163175
}
164-
}
176+
}

media/json-jackson/src/main/resources/org/glassfish/jersey/jackson/localization.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2023, 2025 Oracle and/or its affiliates. All rights reserved.
33
#
44
# This program and the accompanying materials are made available under the
55
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -13,6 +13,7 @@
1313
#
1414
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
#
16+
error.configuring=Error configuring the DefaultJacksonJaxbJsonProvider: {0}.
1617
error.jackson.streamreadconstraints=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.15?
1718
error.jackson.streamreadconstraints218=Error setting StreamReadConstraints: {0}. Possibly not Jackson 2.18?
1819
error.modules.not.loaded=Jackson modules could not be loaded: {0}

tests/integration/pom.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@
8080
<module>jersey-2846</module>
8181
<module>jersey-2878</module>
8282
<module>jersey-2892</module>
83-
<module>jersey-3662</module>
84-
<module>jersey-3796</module>
83+
<module>jersey-3662</module>
84+
<module>jersey-3796</module>
8585
<module>jersey-780</module>
8686
<module>jersey-3670</module>
8787
<module>jersey-3992</module>
@@ -99,6 +99,7 @@
9999
<module>portability-jersey-1</module>
100100
<module>portability-jersey-2</module>
101101
<module>property-check</module>
102+
<module>resteasy-client</module>
102103
<module>security-digest</module>
103104
<module>servlet-2.5-autodiscovery-1</module>
104105
<module>servlet-2.5-autodiscovery-2</module>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved.
5+
6+
This program and the accompanying materials are made available under the
7+
terms of the Eclipse Public License v. 2.0, which is available at
8+
http://www.eclipse.org/legal/epl-2.0.
9+
10+
This Source Code may also be made available under the following Secondary
11+
Licenses when the conditions for such availability set forth in the
12+
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
13+
version 2 with the GNU Classpath Exception, which is available at
14+
https://www.gnu.org/software/classpath/license.html.
15+
16+
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
17+
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
22+
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<parent>
26+
<groupId>org.glassfish.jersey.tests.integration</groupId>
27+
<artifactId>project</artifactId>
28+
<version>2.47-SNAPSHOT</version>
29+
</parent>
30+
31+
<artifactId>resteasy-client</artifactId>
32+
33+
<packaging>war</packaging>
34+
<name>jersey-tests-integration-resteasy-client</name>
35+
36+
<description>
37+
Jersey tests for Spring.Boot / Resteasy integration
38+
</description>
39+
40+
<dependencies>
41+
<dependency>
42+
<groupId>org.jboss.resteasy</groupId>
43+
<artifactId>resteasy-client</artifactId>
44+
<version>5.0.10.Final</version> <!-- Can use 3.5.16.Final -->
45+
<exclusions>
46+
<exclusion>
47+
<artifactId>commons-logging</artifactId>
48+
<groupId>commons-logging</groupId>
49+
</exclusion>
50+
<exclusion>
51+
<groupId>commons-codec</groupId>
52+
<artifactId>commons-codec</artifactId>
53+
</exclusion>
54+
</exclusions>
55+
</dependency>
56+
57+
<dependency>
58+
<groupId>org.glassfish.jersey.test-framework</groupId>
59+
<artifactId>jersey-test-framework-core</artifactId>
60+
<scope>test</scope>
61+
</dependency>
62+
63+
<dependency>
64+
<groupId>org.glassfish.jersey.containers</groupId>
65+
<artifactId>jersey-container-servlet</artifactId>
66+
<scope>test</scope>
67+
</dependency>
68+
69+
<dependency>
70+
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
71+
<artifactId>jersey-test-framework-provider-external</artifactId>
72+
<scope>test</scope>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
76+
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
77+
<scope>test</scope>
78+
</dependency>
79+
80+
<dependency>
81+
<groupId>commons-logging</groupId>
82+
<artifactId>commons-logging</artifactId>
83+
<scope>test</scope>
84+
</dependency>
85+
<dependency>
86+
<groupId>org.glassfish.jersey.media</groupId>
87+
<artifactId>jersey-media-json-jackson</artifactId>
88+
<scope>test</scope>
89+
</dependency>
90+
</dependencies>
91+
92+
<build>
93+
<plugins>
94+
<plugin>
95+
<groupId>org.apache.maven.plugins</groupId>
96+
<artifactId>maven-compiler-plugin</artifactId>
97+
</plugin>
98+
<plugin>
99+
<groupId>org.apache.maven.plugins</groupId>
100+
<artifactId>maven-failsafe-plugin</artifactId>
101+
</plugin>
102+
</plugins>
103+
</build>
104+
</project>
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.tests.springboot;
18+
19+
import javax.ws.rs.POST;
20+
import javax.ws.rs.Path;
21+
import javax.ws.rs.Produces;
22+
import javax.ws.rs.client.Entity;
23+
import javax.ws.rs.core.Application;
24+
import javax.ws.rs.core.Configuration;
25+
import javax.ws.rs.core.Context;
26+
import javax.ws.rs.core.MediaType;
27+
import javax.ws.rs.core.MultivaluedMap;
28+
import javax.ws.rs.core.Response;
29+
import javax.ws.rs.ext.Providers;
30+
31+
import org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider;
32+
import org.glassfish.jersey.server.ResourceConfig;
33+
import org.glassfish.jersey.test.JerseyTest;
34+
import org.hamcrest.Matcher;
35+
import org.hamcrest.MatcherAssert;
36+
import org.hamcrest.Matchers;
37+
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
38+
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
39+
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
40+
import org.junit.jupiter.api.Assertions;
41+
import org.junit.jupiter.api.Test;
42+
43+
import java.io.IOException;
44+
import java.io.InputStream;
45+
import java.lang.annotation.Annotation;
46+
import java.lang.reflect.Type;
47+
import java.util.concurrent.CountDownLatch;
48+
import java.util.concurrent.atomic.AtomicReference;
49+
import java.util.logging.ConsoleHandler;
50+
import java.util.logging.Level;
51+
import java.util.logging.LogRecord;
52+
import java.util.logging.Logger;
53+
54+
public class RestEasyClientTest extends JerseyTest {
55+
56+
private static final CountDownLatch readFromLatch = new CountDownLatch(1);
57+
58+
@Path("/")
59+
public static class RestEasyClientTestResource {
60+
@POST
61+
@Path("/test")
62+
@Produces(MediaType.APPLICATION_JSON)
63+
public String testPost(String echo) {
64+
return echo;
65+
}
66+
}
67+
68+
@Override
69+
protected Application configure() {
70+
return new ResourceConfig(RestEasyClientTestResource.class);
71+
}
72+
73+
@Test
74+
public void test() throws InterruptedException {
75+
AtomicReference<String> messageRef = new AtomicReference<>();
76+
Logger logger = Logger.getLogger(DefaultJacksonJaxbJsonProvider.class.getName());
77+
logger.addHandler(new ConsoleHandler() {
78+
@Override
79+
public void publish(LogRecord record) {
80+
messageRef.set(record.getMessage());
81+
}
82+
});
83+
logger.setLevel(Level.FINE);
84+
85+
final ResteasyClient client = new ResteasyClientBuilderImpl().build();
86+
87+
client.register(TestDefaultJacksonJaxbJsonProvider.class);
88+
89+
try (final Response r = client.target(target().getUri()).path("/test")
90+
.request().post(Entity.entity("{\"test\": \"test\"}", MediaType.APPLICATION_JSON))) {
91+
Object o = r.readEntity(Object.class);
92+
Assertions.assertTrue(o.toString().contains("test"));
93+
readFromLatch.await();
94+
Assertions.assertEquals(0, readFromLatch.getCount(), "DefaultJacksonJaxbJsonProvider has not been used");
95+
}
96+
97+
client.close();
98+
MatcherAssert.assertThat(messageRef.get(), Matchers.notNullValue());
99+
100+
}
101+
102+
public static class TestDefaultJacksonJaxbJsonProvider extends DefaultJacksonJaxbJsonProvider {
103+
public TestDefaultJacksonJaxbJsonProvider(@Context Providers providers, @Context Configuration config) {
104+
super(providers, config);
105+
}
106+
107+
@Override
108+
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
109+
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
110+
readFromLatch.countDown();
111+
return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
112+
}
113+
}
114+
115+
}

0 commit comments

Comments
 (0)