Reputation: 206
I am using Jackson json provider with Jersey 2.0. I have a Web resource like this:
@Path("/accesstokens")
public class AccessTokensService {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response generate(UserCredentials creds) {
System.out.println("In generate method..");
System.out.println(creds);
try {
// Authenticate .. generate token ..
return Response.ok(token, MediaType.APPLICATION_JSON).build();
}
catch (Exception e) {
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
}
The UserCredentials Pojo class is as follows:
public class UserCredentials {
private String username;
private String password;
private String ipAddress;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
}
Here is the relevant snippet from web.xml:
<servlet>
<servlet-name>jersey-rest-service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.xxxxx.apps.ws.services;com.fasterxml.jackson.jaxrs.json;com.xxxxxx.apps.servlet;com.xxxxxx.apps.ws.filters</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.xxxxxx.apps.ws.filters.LoggingFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Here is how the POST entity data looks like:
{"username":"xxxxx", "password":"xxxxxx", "ipAddress": "xxx.xxx.xxx.xxx"}
Unfortunately, the Jackson provider does not deserialize the above JSON. A null UserCredentials object is injected into the above Web resource POST method. If I use a custom MessageBodyReader, my Reader's readFrom method is invoked and I am able to create the UserCredentials pojo which is then available in the POST method.
A couple of questions:
1) Do I need to do any special annotation on the Pojo for Jackson to recognize it? Does the Pojo's package need to be added in web.xml?
2) Is this property in web.xml relevant anymore: "com.sun.jersey.api.json.POJOMappingFeature" ?
3) Do I need to add an ObjectMapper? I think it needs to be done only for custom cases, but please advise.
3) Any other gotchas?? Is there a way to debug code in Jackson?
Thanks.
Upvotes: 4
Views: 3403
Reputation: 206
I figured what was wrong. I had attached a LoggingFilter to process the Request. It was reading the entity off of the entity stream. Thus there was nothing left for Jackson to read and process. Silly me!
Upvotes: 0
Reputation: 116620
If you use the standard Jackson 2.x JAX-RS provider from:
https://github.com/FasterXML/jackson-jaxrs-providers
you should not have to do anything more than add it in classpath; it has SPI metadata that should auto-register provider.
Jackson 1.x provider did not add this, for fear that it might interfere with other options. But with 2.x there seemed to be no point in not doing this.
Upvotes: 0
Reputation: 2830
1) You don't need have any special annotation
2) No POJOMappingFeature does not seem to be relevant anymore
3) No you don't need to add an ObjectMapper
4) Yes any other gotchas:
Write a class extending javax.ws.rs.core.Application
and add the JacksonFeature to your configured classes (you have to have it in your classpath, add to your maven config):
package com.example;
public class YourApplication extends Application {
@Override
public final Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<>(1);
set.add(JacksonFeature.class);
return set;
}
}
Add the following parameter in your web.xml under the servlet config for Jersey:
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.example.YourApplication</param-value>
</init-param>
That should do it. Unfortunately it did get a little harder with jersey 2.0.
Upvotes: 2