Marshaling / Demarshaling JSON with Java EE 7 / Glassfish 4.1 results in null object
I upgraded to Java EE 7 from Java EE 6 and some of my REST services have stopped working. By all accounts, it looks like this change happened when Jersey switched from Jackson to MOXy in Java EE 7.
My service looks like this:
@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 therefore generates a NullPointerException
when presented using JSON. It works great when presented XML. ObjectRequest
is a generic class that I use to wrap a request with an authentication content standard for several different types of requests.
I tested a similar service @GET
to return an instance ObjectRequest<Access>
filled with garbage data. It works well again when using XML, but returns null
(no exception) when I try to return JSON.
I found Java EE7 REST Server no longer returns List as JSON to understand the underlying problem, but didn't figure out how I can get this to work in my situation. My class ApplicationConfig
looks like this:
@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 feel like I need to configure the ApplicationConfig class to use Jackson, but I can't see how to generalize the solutions I've found to cover my situation. So there are actually two questions:
- Did I correctly characterize the underlying problem as a kind of flaw in MOXy?
- How can I fix this using MOXy or Jackson (I don't have a preference as long as it works)?
Setting:
- 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>
source to share
You should solve this problem by disabling MOXy (register the class below in getClasses()
) and get rid of the singleton set.add(new JacksonJsonProvider());
. I use this for all my GF4 projects to get 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;
}
}
source to share