2

I am developing a straightforward maven-based JavaEE application in IntelliJ IDEA, and obviously I would like to use Wildfly 8 for both development and production. I simply need to expose some entities through some RESTful web services. Those entities have bidirectional relationships, which leads to a loop when they are going to be serialized into JSON.

Newer versions of Jackson are able to handle this kind of situation with a special annotation. To get that to work, I need to exclude Wildfly's built-in JSON serializer / jackson provider / whatever it is and use the newer version that comes bundled with my application. I have followed the instructions I have found on the web and came up with this jboss-deployment-structure.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.codehaus.jackson.jackson-jaxrs" />
            <module name="org.codehaus.jackson.jackson-core-asl" />
            <module name="org.codehaus.jackson.jackson-mapper-asl" />
            <module name="org.codehaus.jackson.jackson-xc" />
        </exclusions>
    </deployment>
</jboss-deployment-structure>

The problem is, it doesn't work. Even when I set my pom.xml to something like this:

<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.3.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.0.6.Final</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

which clearly indicates that nothing should come bundled with my application, I still get this StackOverflowError (caused by the infinite loop) which roots in org.codehaus.jackson package. This is turn means that built-in version of Jackson is still in the works and is not excluded. How can I fix this?

Thanks in advance.

UPDATES

I changed the title because I guess the problem is even bigger. Either I am doing something terribly wrong or there is a serious problem with Wildfly.

I have created a pom.xml with all the jackson 2 libraries (com.fasterxml.jackson*) with a "compile" scope. The libraries are included in the WEB-INF/lib folder. I wrote a @Provider according to Jackson JAX-RS FAQ and I can verify that it is actually read by the JAX-RS implementation (RestEasy), simply because the deployment fails if I do not include jackson libraries in WEB-INF/lib with a ClassNotFoundException. However, I am still getting infinite recursion errors with org.codehaus.X (Jackson 1).

I don't care how, I just need a solution to fix this infinite recursion in Wildfly.

Arash Shahkar
  • 655
  • 3
  • 12
  • 24
  • The only thing I needed to do was adding this to the war's Manifest: `Dependencies: com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider, org.jboss.resteasy.resteasy-jackson2-provider services` - it grabs and imports the existing jackson2 modules from wildfly. Does that work for you? – mabi Jan 28 '14 at 07:58
  • Why don't you simple create PR to wildfly with upgrade to jackson? That way you will get newer jackson in release itself. Or at least rise jira issue so guys on WF team can track it. – Tomaz Cerar Jan 28 '14 at 17:17
  • @mabi Thanks. I created the MANIFEST.MF file under META-INF path and write it as you said, but it does not work and the infinite loop is still there. Can you please tell me about your POM dependencies too? – Arash Shahkar Jan 29 '14 at 00:12
  • 1
    @ctomc the release *is* shipped with wildfly. But the default is jackson-1, AFAIK. Just trying to figure out a way to enable the jackson-2 module. I'm not using maven, but I think you also need the `jackson-databind` and `jackson-jaxrs-json-provider` artifacts. – mabi Jan 29 '14 at 07:23
  • 1
    I sent a PR with component upgrade https://github.com/wildfly/wildfly/pull/5824 – Tomaz Cerar Jan 31 '14 at 23:26

1 Answers1

2

The solution is to create a class which implement MessageBodyWriter<Object> using Jackson's ObjectMapper:

@Provider
@Produces("application/json")
public class JacksonMapper implements MessageBodyWriter<Object> {

    @Override
    public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public long getSize(Object object, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
        return 0;
    }

    @Override
    public void writeTo(Object object, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap, OutputStream outputStream)
            throws IOException, WebApplicationException {
        outputStream.write(new ObjectMapper().writeValueAsBytes(object));
    }

}

There's no need for any exclusion or Wildfly-specific descriptors.

It doesn't matter if you include the dependencies or not (compile or provided scopes both work fine) as Jackson 2 is included in Wildfly. However, for an unknown reason, it is near to impossible to deactivate Jackson 1.

This solution brings Jackson 2 into the works. Now you can easily avoid serialization loops using the @JsonIdentityInfo annotation. More info here.

Arash Shahkar
  • 655
  • 3
  • 12
  • 24