I have a JAX-RS REST service using Jersey. I use JAXB for JSON marshalling (ie. @XmlRootElement) One of the method returns a list of objects persisted with JPA.
When this list contains entries it works as I expect. Example:
{"androidDevice":[{"email":"[email protected]","timeCreated":"2012-10-19T
22:41:26.862+02:00"},{"email":"[email protected]","timeCreated":"2012-10-
19T22:41:38.093+02:00"}]}
However, if the list is empty (or null) I would expect it to return {}.
Instead it returns null. Example:
$ curl -i -H "Accept: application/json" http://....
HTTP/1.1 200 OK
Content-Type: application/json
null
Here is the code
@GET
@Produces( { MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML})
public List<AndroidDevice> getAndroidDevices() {
logger.info("getAndroidDevices method called");
EntityManager entityManager = entityMangerFactory.createEntityManager();
List<AndroidDevice> resultList = entityManager.createNamedQuery(AndroidDevice.QUERY_ALL_ENTRIES,
AndroidDevice.class).getResultList();
//avoid returning content null. (doesn't work)
if(resultList==null){
resultList=new ArrayList<AndroidDevice>();
}
return resultList;
}
Is there any way to get Jersey to return an empty JSON list (besides hardcoding a ResponseBuilder) ?
Should I instead provide a different response code for such events?
Update: Got a tips through twitter about this bug report which concludes with that they won't fix it http://java.net/jira/browse/JERSEY-339
Update2: In addition to the solution below, since I was using an Application for configuration (refered to in web.xml), I had to manually add the Provider class there. Here is the relevant code.
public class JAXRSApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<Class<?>>();
//Add all endpoints to this set
set.add(AndroidDeviceEndpoint.class);
//Add Providers
set.add(JAXBContextResolver.class);
return set;
}
}
To achieve more important JSON format changes, you will need to configure Jersey JSON procesor itself. Various configuration options could be set on an JSONConfiguration instance. The instance could be then further used to create a JSONConfigurated JSONJAXBContext, which serves as a main configuration point in this area. To pass your specialized JSONJAXBContext to Jersey, you will finally need to implement a JAXBContext ContextResolver:
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private final JAXBContext context;
private final Set<Class> types;
private Class[] ctypes = { AndroidDevice.class}; //your pojo class
public JAXBContextResolver() throws Exception {
this.types = new HashSet(Arrays.asList(ctypes));
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
ctypes); //json configuration
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return (types.contains(objectType)) ? context : null;
}
}
refer to jersey official document for detailed information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With