Jackson 2 on Wildfly 10: How to load ProviderBase?

2019-07-13 03:02发布

问题:

There seems to be a lot of questions related to Wildfly and Jackson, yet I could not solve my problem despite searching the site far and wide...

I want to use Jackson 2 to handle JSON serialization on an app deployed on Wildfly 10, but I keep getting stuck on loading the com.fasterxml.jackson.jaxrs.base.ProviderBase class.

Offending code:

@Provider
public class CustomJsonProvider extends ResteasyJackson2Provider {

    @Inject
    private CustomSerializer customSerializer;

    private List<JsonSerializer<?>> getSerializers() {

        final List<JsonSerializer<?>> result = new ArrayList<>();

        // Add custom serializers here.
        result.add(customSerializer);

        return result;
    }

    @Override
    public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {

        final List<JsonSerializer<?>> serializers = getSerializers();
        final ObjectMapper mapper = locateMapper(type, mediaType);
        final SimpleModule zeModule = new SimpleModule("App", Version.unknownVersion(), serializers);

        mapper.registerModule(zeModule);
        this.setMapper(mapper);

        super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);
    }

}

In my pom.xml, I have:

<dependencies>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.18.Final</version>
        <scope>provided</scope>
        <type>jar</type>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.18.Final</version>
    </dependency>
    <!-- dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-base</artifactId>
        <version>2.5.4</version>
        <scope>provided</scope>
    </dependency -->
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

And in the jboss-deployment-structure.xml file:

<deployment>
    <exclusions>
        <module name="org.apache.commons.logging" />
        <module name="org.apache.log4j" />
        <module name="org.jboss.logging" />
        <module name="org.jboss.logging.jul-to-slf4j-stub" />
        <module name="org.jboss.logmanager" />
        <module name="org.jboss.logmanager.log4j" />
        <module name="org.slf4j.impl" />
        <module name="org.codehaus.jackson" />
        <module name="org.codehaus.jackson.jackson-mapper-asl" />
        <module name="org.codehaus.jettison" />
        <module name="org.jboss.resteasy.resteasy-jackson-provider" />
        <module name="org.jboss.resteasy.resteasy-jettison-provider" />
    </exclusions>
    <dependencies>
        <module name="org.jboss.resteasy.resteasy-jackson2-provider" services="import"/>
    </dependencies>
</deployment>

With this configuration, compile and deployment go smoothly, but on runtime, I get the following exception:

Caused by: java.lang.LinkageError: loader constraint violation: when resolving overridden method "com.my.package.CustomJsonProvider$Proxy$_$$WeldClientProxy.disable(Lcom/fasterxml/jackson/databind/SerializationFeature;)Lcom/fasterxml/jackson/jaxrs/base/ProviderBase;" the class loader (instance of org/jboss/modules/ModuleClassLoader) of the current class, com/my/package/CustomJsonProvider$Proxy$$$_WeldClientProxy, and its superclass loader (instance of org/jboss/modules/ModuleClassLoader), have different Class objects for the type com/fasterxml/jackson/jaxrs/base/ProviderBase used in the signature

From what I gathered, there is a different version of ProviderBase loaded by Wildfly's classloader. So I figured that using the provided version would solve the problem (with the possible side-effect of unexpect implementation differences, but still).

Problem is, if I uncomment the commented dependency in the POM, de facto using the version of com.fasterxml.jackson.jaxrs:jackson-jaxrs-baseprovided in Wildlfy, it complains again at runtime:

Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.jaxrs.base.ProviderBase from [Module "deployment.myapp-ear-0.1-SNAPSHOT.ear.myapp-core-0.1-SNAPSHOT.jar:main" from Service Module Loader]

This seems to be a problem of conflicting classloaders. What am I missing and how can I solve this?