diff --git a/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/CombinedAnnotationBean.java b/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/CombinedAnnotationBean.java
index 06a23c47be..2ac0ac634b 100644
--- a/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/CombinedAnnotationBean.java
+++ b/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/CombinedAnnotationBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -10,7 +10,7 @@
package org.glassfish.jersey.examples.jackson;
-import javax.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/MyObjectMapperProvider.java b/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/MyObjectMapperProvider.java
index e32135878f..81bda853a0 100644
--- a/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/MyObjectMapperProvider.java
+++ b/examples/json-jackson/src/main/java/org/glassfish/jersey/examples/jackson/MyObjectMapperProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
@@ -19,7 +19,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.type.TypeFactory;
-import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
+import com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
/**
* TODO javadoc.
@@ -63,7 +63,7 @@ private static ObjectMapper createDefaultMapper() {
private static AnnotationIntrospector createJaxbJacksonAnnotationIntrospector() {
- final AnnotationIntrospector jaxbIntrospector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
+ final AnnotationIntrospector jaxbIntrospector = new JakartaXmlBindAnnotationIntrospector(TypeFactory.defaultInstance());
final AnnotationIntrospector jacksonIntrospector = new JacksonAnnotationIntrospector();
return AnnotationIntrospector.pair(jacksonIntrospector, jaxbIntrospector);
diff --git a/media/json-jackson/pom.xml b/media/json-jackson/pom.xml
index cbc01771b5..9456ee6234 100644
--- a/media/json-jackson/pom.xml
+++ b/media/json-jackson/pom.xml
@@ -1,7 +1,7 @@
+ com.fasterxml.jackson.module
+ jackson-module-jakarta-xmlbind-annotations
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+
+
+ jakarta.activation
+ jakarta.activation-api
+
+
+
+
+
javax.xml.bind
jaxb-api
2.3.1
+ test
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
junit
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
index 2ad04c18ca..f4f0f3f71f 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -31,15 +31,15 @@
public class DefaultJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
//do not register JaxbAnnotationModule because it brakes default annotations processing
- private static final String EXCLUDE_MODULE_NAME = "JaxbAnnotationModule";
+ private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"};
public DefaultJacksonJaxbJsonProvider() {
- super();
+ super(new JacksonMapperConfigurator(null, DEFAULT_ANNOTATIONS));
findAndRegisterModules();
}
public DefaultJacksonJaxbJsonProvider(final Annotations... annotationsToUse) {
- super(annotationsToUse);
+ super(new JacksonMapperConfigurator(null, annotationsToUse));
findAndRegisterModules();
}
@@ -49,7 +49,9 @@ private void findAndRegisterModules() {
final ObjectMapper mapper = _mapperConfig.getConfiguredMapper();
final List modules = ObjectMapper.findModules();
- modules.removeIf(mod -> mod.getModuleName().contains(EXCLUDE_MODULE_NAME));
+ for (String exludeModuleName : EXCLUDE_MODULE_NAMES) {
+ modules.removeIf(mod -> mod.getModuleName().contains(exludeModuleName));
+ }
defaultMapper.registerModules(modules);
if (mapper != null) {
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonMapperConfigurator.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonMapperConfigurator.java
new file mode 100644
index 0000000000..7be7b11c6c
--- /dev/null
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonMapperConfigurator.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.jackson.internal;
+
+import com.fasterxml.jackson.databind.AnnotationIntrospector;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.Annotations;
+import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JsonMapperConfigurator;
+
+import java.security.AccessController;
+import java.util.ArrayList;
+
+public class JacksonMapperConfigurator extends JsonMapperConfigurator {
+ public JacksonMapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations) {
+ super(mapper, defAnnotations);
+ }
+
+ @Override
+ protected AnnotationIntrospector _resolveIntrospectors(Annotations[] annotationsToUse) {
+ // Let's ensure there are no dups there first, filter out nulls
+ ArrayList intr = new ArrayList();
+ for (Annotations a : annotationsToUse) {
+ if (a != null) {
+ _resolveIntrospector(a, intr);
+ }
+ }
+ int count = intr.size();
+ if (count == 0) {
+ return AnnotationIntrospector.nopInstance();
+ }
+ AnnotationIntrospector curr = intr.get(0);
+ for (int i = 1, len = intr.size(); i < len; ++i) {
+ curr = AnnotationIntrospector.pair(curr, intr.get(i));
+ }
+ return curr;
+ }
+
+ protected void _resolveIntrospector(Annotations ann, ArrayList intr) {
+ switch (ann) {
+ case JAXB:
+ /* For this, need to use indirection just so that error occurs
+ * when we get here, and not when this class is being loaded
+ */
+ try {
+ if (_jaxbIntrospectorClass == null) {
+ _jaxbIntrospectorClass = JakartaXmlBindAnnotationIntrospector.class;
+ }
+ intr.add(JakartaXmlBindAnnotationIntrospector.class.newInstance());
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to instantiate JakartaXmlBindAnnotationIntrospector: "
+ + e.getMessage(), e);
+ }
+
+ if (jaxb2AnnotationIntrospector.get() == true) {
+ Class extends AnnotationIntrospector> tempJaxbIntrospectorClass = _jaxbIntrospectorClass;
+ _jaxbIntrospectorClass = null;
+ intr.add(super._resolveIntrospector(ann));
+ _jaxbIntrospectorClass = tempJaxbIntrospectorClass;
+ }
+ break;
+ default:
+ intr.add(super._resolveIntrospector(ann));
+ }
+ }
+
+ private static LazyValue jaxb2AnnotationIntrospector = Values.lazy((Value) () -> {
+ final Class> aClass = AccessController.doPrivileged(
+ ReflectionHelper.classForNamePA("com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector")
+ );
+ return aClass != null;
+ });
+}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
index 1c0a882fc2..eb7c072f0c 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJaxbJsonProvider.java
@@ -63,4 +63,10 @@ public JacksonJaxbJsonProvider(ObjectMapper mapper, Annotations[] annotationsToU
{
super(mapper, annotationsToUse);
}
+
+ // Do not erase - Jersey required constructor
+ protected JacksonJaxbJsonProvider(JsonMapperConfigurator configurator)
+ {
+ super(configurator);
+ }
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
index 9fecf427a9..0871ece423 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/JacksonJsonProvider.java
@@ -137,6 +137,11 @@ public JacksonJsonProvider(ObjectMapper mapper, Annotations[] annotationsToUse)
super(new JsonMapperConfigurator(mapper, annotationsToUse));
}
+ // Do not erase - Jersey required constructor
+ protected JacksonJsonProvider(JsonMapperConfigurator configurator) {
+ super(configurator);
+ }
+
/**
* Method that will return version information stored in and read from jar
* that contains this class.
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JacksonJaxb2JsonProviderTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JacksonJaxb2JsonProviderTest.java
new file mode 100644
index 0000000000..09a3c8b7c2
--- /dev/null
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/JacksonJaxb2JsonProviderTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.jackson.internal;
+
+import jakarta.ws.rs.core.Application;
+import org.glassfish.jersey.jackson.internal.model.Jaxb2ServiceTest;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+
+public final class JacksonJaxb2JsonProviderTest extends JerseyTest {
+
+ @Override
+ protected final Application configure() {
+ return new ResourceConfig(Jaxb2ServiceTest.class);
+ }
+
+ @Test
+ public final void testJavaOptional() {
+ final String response = target("entity/simple").request().get(String.class);
+ assertEquals("{\"name\":\"Hello\",\"value\":\"World\"}", response);
+ }
+}
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/Jaxb2ServiceTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/Jaxb2ServiceTest.java
new file mode 100644
index 0000000000..a679142c55
--- /dev/null
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/Jaxb2ServiceTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.jackson.internal.model;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import javax.xml.bind.annotation.XmlElement;
+
+import java.util.Optional;
+
+@Path("/entity/")
+public final class Jaxb2ServiceTest {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/simple")
+ public final EntityTest simple() {
+ return new EntityTest("Hello", "World");
+ }
+
+ private static final class EntityTest {
+
+ private final String name;
+
+ private final String value;
+
+ EntityTest(final String name, final String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ @XmlElement(name = "jaxb")
+ @JsonGetter("name")
+ public final String getName() {
+ return name;
+ }
+
+ @JsonGetter("value")
+ public final Optional getValue() {
+ return Optional.ofNullable(value);
+ }
+ }
+}
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/ServiceTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/ServiceTest.java
index 23ac90de61..314cc99d9a 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/ServiceTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/model/ServiceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
diff --git a/pom.xml b/pom.xml
index 0d6fe4d54c..a205697b71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@