4

I upgraded to Java EE 7 from Java EE 6 and some of my REST services stopped working. Narrowing it down, it appears this change seems to have come about when Jersey switched from Jackson to MOXy in Java EE 7.

My service looks like:

@Stateless
@Path("access")
public class AccessFacadeREST extends AbstractFacade<Access> {
    @PersistenceContext(unitName = "AccessServerPU")
    private EntityManager em;

    public AccessFacadeREST() {
        super(Access.class);
    }

    @POST
    @Consumes({"application/xml", "application/json"})
    @Produces({"application/xml", "application/json"})
    public ObjectResponse create(@Context HttpServletRequest requestContext,
                                 @Context SecurityContext context,
                                 ObjectRequest<Access> req) {
        req.setHostname(requestContext.getRemoteAddr());
        return AccessValidation.create(em, req);
    }
}

Here req is null and so generates a NullPointerException when it is presented using JSON. It works fine when presented as XML. ObjectRequest is a generic class I use to wrap the request with authentication content standard for several different types of requests.

I tested a similar @GET service to return an ObjectRequest<Access> instance filled with junk data. It again works well when using XML, but returns null (with no exception raised) when I attempt to return JSON.

I found Java EE7 REST server no longer returning List as JSON useful to understand the underlying problem, but didn't see how I could get this to work in my situation. My ApplicationConfig class looks like:

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {

    @Override
    public Set<Object> getSingletons() {
        Set<Object> set = new HashSet<>();
        log.info("Enabling custom Jackson JSON provider");
        set.add(new JacksonJsonProvider());
        return set;
    }

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> map = new HashMap<>();
        log.info("Disabling MOXy JSON provider");
        map.put("jersey.config.disableMoxyJson.server", true);
        return map;
    }

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        addRestResourceClasses(resources);
        return resources;
    }

    private void addRestResourceClasses(Set<Class<?>> resources) {
        resources.add(AccessFacadeREST.class);
    }
}

I think I need to configure the ApplicationConfig class to use Jackson, but I don't see how to generalize the solutions I've found to cover my situation. So, two questions really:

  1. Have I properly characterized the underlying problem as being some sort of deficiency with MOXy?
  2. How can I fix this using either MOXy or Jackson (I don't have a preference which, just as long as it works)?

Setup:

  • Netbeans 8.0.2
  • Glassfish 4.1
  • JDK 8 / JRE 8U25 (64 bit)

Edit in response to the question below...

The project pom.xml has the following entry:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.4.4</version>
</dependency>
Community
  • 1
  • 1
andand
  • 17,134
  • 11
  • 53
  • 79
  • Are you using the fasterxml jackson json provider under the group `com.fasterxml.jackson.jaxrs` ? I recall having a similar problem when I migrated between Jersey versions, but it was quite a while ago. The details escape me. – Deepak Bala Jan 07 '15 at 06:51
  • @DeepakBala See edit above, but in short, yes, I have that entry in the project's pom.xml file. – andand Jan 08 '15 at 04:13

1 Answers1

3

You should be able to solve this by disabling MOXy (register the class below in getClasses()) and get rid of your set.add(new JacksonJsonProvider()); singleton. I use this for all my GF4 projects to force Jersey to use Jackson.

/**
 * Feature to disable Moxy and Enable Jackson processing
 */
private static class Jackson2Feature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        final String disableMoxy = PropertiesHelper.getPropertyNameForRuntime(
                CommonProperties.MOXY_JSON_FEATURE_DISABLE,
                context.getConfiguration().getRuntimeType());
        context.property(disableMoxy, true);

        // add the default Jackson exception mappers and allow jaxb annotations
        context.register(JsonParseExceptionMapper.class);
        context.register(JacksonJaxbJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class);
        return true;
    }
}
Baldy
  • 2,002
  • 14
  • 14
  • 3
    Or you can just use [jersey-media-json-jackson](https://jersey.java.net/documentation/latest/media.html#json.jackson) (which Glassfish also comes shipped with), and just `register(JacksonFeature.class)`. One liner. Moxy is automatically disabled. See [Note](https://jersey.java.net/documentation/latest/media.html#json.moxy) – Paul Samsotha Feb 12 '15 at 14:58