How do I get Wildfly to use additional Jackson Datatypes?

xenoterracide picture xenoterracide · Mar 2, 2014 · Viewed 9k times · Source

I'm getting this error

03:33:14,938 WARN  [org.jboss.resteasy.core.ExceptionHandler] (default task-1) Failed executing PUT /individual/5a247ce9-0a73-4373-89ce-e4177f911259/activities/432e6e5b-4185-462f-b57e-9ec04bec3d58: org.jboss.resteasy.spi.ReaderException: org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class java.time.Instant] from JSON String; no single-String constructor/factory method (through reference chain: com.lm.activity.DTOActivity["created"])

It's because Wildfly doesn't know how to handle an instant. By reading the error I could simply handle it in that class, but that seems silly. I'm using the following library and am shipping it and all of an updated jackson in my war file, but that alone isn't doing it.

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.2</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.3.2</version>
    </dependency>

I found this wiki

but my implementation is problematic, the class definition statement has an error

package com.lm.infrastructure;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
@Produces( MediaType.APPLICATION_JSON )
public class JacksonProducer implements ContextResolver<ObjectMapper> {

    public JacksonProducer() throws Exception {
        this.json = new ObjectMapper()
                .findAndRegisterModules()
                .configure( FAIL_ON_UNKNOWN_PROPERTIES, false );

    }

    @Override
    public ObjectMapper getContext( Class<?> type ) {
        return json;
    }
    private final ObjectMapper json;
}

I put this in my web.xml (not to be confused with jboss-web.xml)

<web-app ...
  <context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>com.lm.infrastructure.JacksonProducer</param-value>
  </context-param>
</web-app>

I tried modifying modules/system/layers/base/com/fasterxml/jackson/jaxrs/jackson-jaxrs-json-provider/main/module.xml which seems to be suggested here

 <module xmlns="urn:jboss:module:1.1" name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider">
 <resources>
    <resource-root path="jackson-jaxrs-json-provider-2.3.2.jar"/>
    <resource-root path="jackson-jaxrs-base-2.3.2.jar"/>
    <resource-root path="jackson-module-jaxb-annotations-2.3.2.jar"/>
    <resource-root path="jackson-databind-2.3.2.jar"/>
    <resource-root path="jackson-datatype-jsr310-2.3.2.jar"/>
    <!-- Insert resources here -->
</resources>

<dependencies>
    <module name="javax.api"/>
    <module name="javax.ws.rs.api"/>
    <module name="javax.xml.bind.api"/>
    <module name="com.fasterxml.jackson.core.jackson-annotations"/>
    <module name="com.fasterxml.jackson.core.jackson-core"/>
    <module name="com.fasterxml.jackson.core.jackson-databind"/>
    <module name="com.fasterxml.jackson.datatype.jackson-datatype-jsr310"/>
</dependencies>
</module>

My primary goal is to get jsr310 serializing and deserializing. What do I need to do to make this happen? but I suspect that the answer would apply to any additional datatype that doesn't ship with wildfly. (I think this issue is related )

Answer

xenoterracide picture xenoterracide · Mar 12, 2014

Ultimately I was affected by This Bug in 8.0.0.Final it should be fixed in 8.0.1, until then I've downgraded to 8.0.0.CR1.

Here's my Final pom.xml, note that I'm using 2.2.3

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.2.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.2.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.2.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.2.3-beta5</version>
    </dependency>

my web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
 ...
    <context-param>
        <param-name>resteasy.providers</param-name>
        <param-value>com.lm.infrastructure.JacksonProducer</param-value>
    </context-param>
</web-app>

my jboss-deployment-structure.xml this is required, and I didn't have it previously

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
        <deployment>
                <exclusions>
                        <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>
</jboss-deployment-structure>

My Producer

package com.lm.infrastructure;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import com.fasterxml.jackson.databind.ObjectMapper;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
@Produces( MediaType.APPLICATION_JSON )
public class JacksonProducer implements ContextResolver<ObjectMapper> {

    public JacksonProducer() throws Exception {
        this.json
            = new ObjectMapper()
            .findAndRegisterModules()
            .configure( WRITE_DATES_AS_TIMESTAMPS, false )
            .configure( FAIL_ON_UNKNOWN_PROPERTIES, false );
    }

    @Override
    public ObjectMapper getContext( Class<?> objectType ) {
        return json;
    }

    private final ObjectMapper json;
}

and last but not least my arquillian war generation

public static WebArchive testWar() {
    File[] libs
            = Maven.resolver().loadPomFromFile( "pom.xml" )
            .resolve(
                    "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
            )
            .withTransitivity()
            .asFile();

    return ShrinkWrap.create( WebArchive.class )
            .setWebXML( new File( "src/main/webapp/WEB-INF/web.xml" ) )
            .addAsWebInfResource( new File( "src/main/webapp/WEB-INF/jboss-web.xml" ) )
            .addAsWebInfResource( new File( "src/main/resources/logback.xml" ) )
            .addAsWebInfResource( new File( "src/main/webapp/WEB-INF/jboss-deployment-structure.xml" ) )
            .addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" )
            .addPackages( false, Filters.exclude( ".*Test.*" ), getCorePackages() )
            .addAsLibraries( libs );
}