ExceptionMapper的Jersey / Jackson Exception问题

时间:2011-04-29 14:07:25

标签: java exception exception-handling jersey jackson

我正在使用Jersey为外界提供java REST服务。我提供了一些采用JSON的功能,我将Jackson框架与jersey结合使用,将它们转换为POJO。

我遇到的问题是,如果将错误的jackson格式发送到服务器,答案(http响应的内容)是杰克逊特定的异常描述。如果我有一个带有属性“surname”的POJO并将json字符串中的“sursname”发送到服务器,我得到:

Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: sun.net.httpserver.FixedLengthInputStream@903025; line: 1, column: 49] (through reference chain: XY["sursname"])

这很好,但我想有自己的回复内容,例如我自己的错误代码。我已经编写了一个自定义ExceptionMapper ,它应该映射所有Throwables。

@Provider
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> {

@Override
public Response toResponse(Exception e) {
    e.printStackTrace();
    return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build();
    }
}

似乎在调用我的webservice方法之前抛出了jackson异常,所以我没有机会映射它?

有没有人有想法?非常感谢对不起我的英语;)

5 个答案:

答案 0 :(得分:16)

你的自定义ExceptionMapper没有捕获异常的原因是因为Jackson库提供了自己的异常映射器,它在你的genereal异常映射器捕获之前捕获异常。

有些人建议您应该为JsonParseExceptionMapper和JacksonMappingExceptionMapper实现自己的异常映射器,但是这会产生不一致的结果。 See this issue on their GitHub

要解决此问题,您必须确保没有注册任何内置的异常映射器。如果您使用 jackson-jaxrs-providers 库用于JSON: jackson-jaxrs-json-provider ,请确保您在Application类中注册 JacksonJaxbJsonProvider.class JacksonJsonProvider.class

$("#cccc, #bccc").select2({
    tags: true,    
    multiple: true,
    selectOnClose: true,
    tokenSeparators: [",", " "]
});

注意 JacksonFeature.class ,因为它注册了内置的ExceptionMappers。还要远离 jersey-media-json-jackson 库,它会自动添加一些内置的异常映射器,而不需要做任何事情。

答案 1 :(得分:2)

我在使用Jackson和Apache CXF的过程中遇到了类似的问题。如果在我的JAX-RS方法中没有发生异常而是在JacksonJsonProvider中发生异常,则不会调用异常映射器。我的解决方案是扩展JacksonJsonProvider,捕获特定的Jackson json异常,并将它们重新抛出为WebApplicationException

这是我的扩展JacksonJsonProvider的覆盖readFrom方法:

    @Override
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
        try {
            return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
        } catch (JsonParseException jpe) {
            throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build());
        } catch (JsonMappingException jme) {
            throw new WebApplicationException(jme, Response
                    .status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n"
                            + jme.getMessage())).build());
        }
    }

答案 2 :(得分:1)

当然之前抛出Jackson异常:调用Jackson提供程序,以便在您的方法中创建一个您期望的对象。但是,使用ExceptionMapper,您不仅可以映射您的异常,还可以映射提供者异常。

您确定您的提供商已注册吗?如果您的方法抛出异常而不是来自提供者,是否会调用它?

如果上一个问题的答案为“是”,请尝试为具体异常而不是Throwable实现ExceptionMapper。

答案 3 :(得分:1)

我遇到了同样的问题并解决了覆盖ExceptionMapper的问题。完善!我需要做的另一件事是,不理解100%是如何为我的应用程序覆盖JacksonProvider(我不知道它是否与我使用的泽西版本相关 - 2.19)。这是我的web.xml部分覆盖它:

<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
    </param-value>

答案 4 :(得分:-1)

感谢您的帮助,JsonParseException的ExceptionMapper没有帮助。我从我的projekt中删除了jackson jar文件并包含了jackson来源。然后我修改了ord.codehaus.jackson.jaxrs.JsonParseExceptionMapper和JacksonMappingExceptionMapper来返回我的自定义响应内容。我对它不满意,但它现在有效!

感谢您的帮助!