I have an @GET
method that is annotated with a @Produces( MediaType.APPLICATION_JSON )
. I'd like to see that call fail when I disable the JSON processing in Jersey, but no matter what I do it continues to generate a JSON output when I access that URL method in the browser.
When I place a breakpoint inside com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider
's constructor I see it is being registered when MessageBodyFactory
is instantiated. In particular, under the line:
final Set<MessageBodyReader> mbrs = Providers.getProviders(locator, MessageBodyReader.class);
The JacksonJsonProvider
is discovered even though I disabled all auto-discoveries. As a result I cannot register my own which provides a custom ObjectMapper. The default one is always used instead.
The method looks like this:
@GET
@Produces( MediaType.APPLICATION_JSON )
public Status getStatus() {
return new Status("test");
}
In my application, I make what I believe to be the proper (even an overkill) configurations:
public class CustomResourceConfig extends ResourceConfig {
public CustomResourceConfig() {
property(CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
property(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE, true);
property(CommonProperties.MOXY_JSON_FEATURE_DISABLE, true);
property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
property(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
property(ServerProperties.MOXY_JSON_FEATURE_DISABLE, true);
property(ServerProperties.JSON_PROCESSING_FEATURE_DISABLE, true);
property(ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
property(ClientProperties.JSON_PROCESSING_FEATURE_DISABLE, true);
packages("test.package.api");
}
}
I have placed the following configs in the web.xml:
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableMetainfServicesLookup</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableJsonProcessing</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableMoxyJson</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.specktro.orchid.deployment.registry.CustomResourceConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
My pom.xml includes the following dependencies:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>
Versions are managed by parent POM, but I need to use Jackson 2.3.2, and I'm using Jersey 2.7 (also tried with 2.6, same results).
I also tried registering a JacksonJaxbJsonProvider
which used my object mapper:
register(new JacksonJaxbJsonProvider(objectMapper, null));
but that results in two JacksonJsonProviders
registered: one for my JacksonJaxbJsonProvider
and one that Jersey registers during initialization and that one gets used so mine is ignored.
How can I get Jersey to use my JacksonJsonProvider
instead of the default one so I can provide my own ObjectMapper
?
UPDATE Of course I also tried creating a custom ContextResolver that provides a custom ObjectMapper and registered it, but it is ignored.
Found the problem!! I was not returning an object like normally people do. Instead I was throwing a subclass of WebApplicationException which shows in the client as a JSON:
public class ApplicationException extends WebApplicationException {
private static final long serialVersionUID = 1L;
public ApplicationException(int errorCode, String message) {
super(Response.status(Response.Status.OK).entity(
JsonNodeFactory.instance.objectNode()
.put("errorCode", errorCode)
.put("errorMessage", message).toString())
.type(MediaType.APPLICATION_JSON).build());
}
}
And THAT is a problem in Jersey... when Jersey handles this exception it does not use the correct Json Provider... instead it registers a default one without my custom settings, and also does not query for the ContextResolver I have registered resulting in an unformatted JSON (I have pretty print turned on on my ObjectMapper).
I opened a bug with Jersey in JIRA: https://java.net/jira/browse/JERSEY-2503
I hope this helps another poor soul trying to handle this case.