异常映射器未按预期工作

3

我正在使用Jersey来实现REST Web服务。

当服务层未返回任何对象时,我通过抛出NotFoundException(包名为com.sun.jersey.api)来处理所有404响应。

例如:

@GET
@Path("/{folderID}")
@Produces(MediaType.APPLICATION_JSON)
public Response getFolder(@PathParam("folderID") int folderID) {
       .
       .
       .
       Folder folderObj = folderService.getFolder(folderID);
       if(folderObj == null){
            throw new NotFoundException("Folder with ID '"+folderID+"'  not found.");
       }
}

我已为这个异常编写了ExceptionMapper。

@Provider
public class NotFoundExceptionMapper implements   ExceptionMapper<NotFoundException> {

public Response toResponse(NotFoundException ex) {
    ErrorMesage errorMessage = new ErrorMessage();
    errorMessage.setCode(Status.NOT_FOUND.getStatusCode());
    errorMessage.setMessage(ex.getMessage());

    return Response.status(Status.NOT_FOUND)
            .entity(errorMessage)
            .type(MediaType.APPLICATION_JSON)
            .build();
}

当我将未知文件夹ID作为路径参数时,会引发异常,但是NotFoundExceptionMapper中的代码没有被调用。(我可以在响应中看到异常消息,但作为'纯文本',即使在映射器中我返回JSON响应; 调试断点也没有命中)。

另外,当我在URI中输入错误的资源名称时,会调用上述异常映射器,但不适用于错误的路径参数。

我还添加了以下异常映射器以响应所有其他异常。

public class GenericExceptionMapper implements  ExceptionMapper<Throwable>{

public Response toResponse(Throwable ex) {
    ErrorMessage errorMessage = new ErrorMessage();
    errorMessage.setCode(Status.INTERNAL_SERVER_ERROR.getStatusCode());
    errorMessage.setMessage(ex.getMessage());


    return Response.status(errorMessage.getCode())
            .entity(errorMessage)
            .type(MediaType.APPLICATION_JSON)
            .build();   
}

每当抛出任何异常(除了映射的异常),上述代码就会被调用,并且我会得到适当的JSON响应。
那么NotFoundException有什么问题呢? 我已经谷歌过这个问题并查看了NotFoundException的源码,但没有找到任何有用的信息,请指导我。

1
你如何注册这些异常映射器? - Jaroslaw Pawlak
尚未测试,但可能与有关... 相关性可以在JavaDoc中找到,其中指出String参数是实体。 - Paul Samsotha
Jersey中是否有内置的映射器用于NotFoundException?NotFoundException的构造函数如下: super(Responses.notFound().entity(message).type("text/plain").build());这是我收到“纯文本”响应的原因吗? - dk_123
谢谢!我也认为我需要创建自己的异常。 我使用了NotFoundException的其他构造函数,它起作用了! 但是我无法在“字符串”中获得所需的消息,我只能获取资源URI。 - dk_123
在Jersey 2.x中,如果您抛出一个带有非空实体的WebApplicationException,它将不会被mapper捕获。javax.ws.rs.NotFoundException扩展了WebApplicationException。在抛出异常之前,请确保不设置实体。 - Filip
显示剩余4条评论
1个回答

3

以下是来自 Jersey ServerRuntime 类的一段代码。它有一个特殊的逻辑:如果 ExceptionWebApplicationException 的实例并且具有主体,则根本不会去调用异常映射器。

private Response mapException(Throwable originalThrowable) throws Throwable {
    if (throwable instanceof WebApplicationException) {
        WebApplicationException webApplicationException = (WebApplicationException)throwable;
     }

    this.processingContext.routingContext().setMappedThrowable(throwable);
    waeResponse = webApplicationException.getResponse();
    if (waeResponse.hasEntity()) {
        LOGGER.log(java.util.logging.Level.FINE, LocalizationMessages.EXCEPTION_MAPPING_WAE_ENTITY(waeResponse.getStatus()), throwable);
        return waeResponse;
    }        

    long timestamp = this.tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
    ExceptionMapper mapper = this.runtime.exceptionMappers.findMapping(throwable);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接