在Jersey中返回JSON或XML for Exceptions

时间:2010-05-20 08:01:20

标签: json rest error-handling exception jersey

我的目标是在找不到对象时在404上返回带有描述性消息的错误bean,并返回所请求的相同MIME类型。

我有一个查找资源,它将基于URI返回XML或JSON中的指定对象(我已经设置了com.sun.jersey.config.property.resourceConfigClass servlet参数,因此我不需要Accept标头。我的JAXBContextResolver在其类型列表中有ErrorBean.class,并为此类返回正确的JAXBContext,因为我可以在日志中看到。)

例如: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");
     }

}

我的NotFoundException看起来像这样:

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());
    }

}

ErrorBean如下:

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

    private String errorMsg;
    private int errorCode;

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

}

然而,当我尝试这个时,我总是得到 204 No Content 响应。我已经乱砍了,如果我返回一个字符串并指定mime类型,这可以正常工作:

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

我也尝试将ErrorBean作为资源返回。这很好用:

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

1 个答案:

答案 0 :(得分:9)

对于那些在未来有类似问题的人......

原来我的代码还可以。我把头发拉了出来,所以我重写了这个模块,但仍然没有到达任何地方。我的浏览器只会坐在那里永远挂起。我开始使用LiveHTTPHeaders(firefox附加组件)检查标头,并注意到发生这种情况时Content-Length大于零。然后我用hurl.it进行测试,发现身体正常恢复。浏览器可以很好地处理XML响应,但是不会显示JSON(因此挂起)。这对我来说很好,因为这纯粹是用于应用程序消费的API而不是用户。有关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)"
}