Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let Jackson use JAXB3 #4963

Merged
merged 2 commits into from
Jan 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 23 additions & 2 deletions media/json-jackson/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2012, 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
Expand Down Expand Up @@ -131,13 +131,34 @@
<artifactId>jakarta.activation-api</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<!-- The last JAX-B API that has maven coordinates which do not colide with Jakarta coordinates -->
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
<exclusions>
<exclusion>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</exclusion>
<exclusion>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!-- The last JAX-B API that has maven coordinates which do not collide with Jakarta coordinates -->
<!-- Do not update -->
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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();
}

Expand All @@ -49,7 +49,9 @@ private void findAndRegisterModules() {
final ObjectMapper mapper = _mapperConfig.getConfiguredMapper();

final List<Module> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<AnnotationIntrospector> intr = new ArrayList<AnnotationIntrospector>();
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<AnnotationIntrospector> 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<Boolean> jaxb2AnnotationIntrospector = Values.lazy((Value<Boolean>) () -> {
final Class<?> aClass = AccessController.doPrivileged(
ReflectionHelper.classForNamePA("com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector")
);
return aClass != null;
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<String> getValue() {
return Optional.ofNullable(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2010, 2021 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 Public License v. 2.0, which is available at
Expand Down Expand Up @@ -1750,6 +1750,12 @@
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
Expand Down
Loading