Returning JSON or XML for Exceptions in Jersey

2019-04-20 05:04发布

问题:

My goal is to have an error bean returned on a 404 with a descriptive message when a object is not found, and return the same MIME type that was requested.

I have a look up resource, which will return the specified object in XML or JSON based on the URI (I have setup the com.sun.jersey.config.property.resourceConfigClass servlet parameter so I dont need the Accept header. My JAXBContextResolver has the ErrorBean.class in its list of types, and the correct JAXBContext is returned for this class because I can see in the logs).

eg: http://foobar.com/rest/locations/1.json

@GET
@Path("{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Location getCustomer(@PathParam("id") int cId) {
   //look up location from datastore
    ....
    if (location == null) {
        throw new NotFoundException("Location" + cId + " is not found");
     }

}

And my NotFoundException looks like this:

public class NotFoundException extends WebApplicationException {

    public NotFoundException(String message) {
        super(Response.status(Response.Status.NOT_FOUND).
                entity(new 
                        ErrorBean(
                           message, 
                           Response.Status.NOT_FOUND.getStatusCode()
                        )
                .build());
    }

}

The ErrorBean is as follows:

@XmlRootElement(name = "error")
public class ErrorBean {

    private String errorMsg;
    private int errorCode;

        //no-arg constructor, property constructor, getter and setters
        ...

}

However, I'm always getting a 204 No Content response when I try this. I have hacked around, and if I return a string and specify the mime type this works fine:

public NotFoundException(String message) {
    super(Response.status(Response.Status.NOT_FOUND).
            entity(message).type("text/plain").build());
}

I have also tried returning an ErrorBean as a resource. This works fine:

{"errorCode":404,"errorMsg":"Location 1 is not found!"}

回答1:

For those with similar issues in the future ...

Turns out my code was OK in the end. I was pulling my hair out, so I rewrote this module, and was still not getting anywhere. My browser would just sit there and hang forever. I started inspecting the headers with LiveHTTPHeaders (firefox add-on), and noticed when this happened Content-Length was larger then zero. I then tested with hurl.it and found out the body was returning normally. The browser would handle the XML response fine, but wouldnt ever display the JSON (thus the hanging). This is fine for my purpose as this is purely an API for application consumption and not for users. There is information on mapping exceptions at the Jersey wiki.

HTTP/1.1 404 Not Found
Content-Type: application/json
Date: Fri, 21 May 2010 06:39:28 GMT
Server: Google Frontend
Cache-Control: private, x-gzip-ok=""
Transfer-Encoding: chunked

{
    "errorCode": "404", 
    "errorMsg": "Could not retrieve entity of kind Location with key Location(10)"
}