ExceptionMapper не работает должным образом

Я использую трикотаж для веб-служб REST.

Я обрабатываю все 404 ответа, выбрасывая NotFoundException (Package com.sun.jersey.api) всякий раз, когда я не получаю какой-либо объект из уровня обслуживания.

e.g.

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

}

Поэтому, когда я указываю неизвестный идентификатор папки в качестве параметра пути, возникает исключение, но код 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, но не нашел ничего полезного, пожалуйста, помогите мне в этом.


person dk_123    schedule 16.11.2015    source источник
comment
Как вы регистрируете эти преобразователи исключений?   -  person Jaroslaw Pawlak    schedule 16.11.2015
comment
Не тестировалось, но может быть связано с этим ... Корреляцию можно найти в javavdoc для NotFoundException, где сказано String arg - это сущность.   -  person Paul Samsotha    schedule 16.11.2015
comment
Я пробовал оба пути. 1. Добавление аннотации @Provider 2. Регистрация ресурса в классе Application   -  person dk_123    schedule 16.11.2015
comment
Я никогда не пробовал регистрировать более одного сопоставителя исключений. Мне интересно, может ли проблема быть в том, что вызван неправильный картограф. В прошлый раз, когда я делал это, у нас был только один преобразователь исключений, принимающий RuntimeException, а затем несколько instanceof внутри для таких случаев, как 404. Все остальные исключения (не охваченные instanceof) привели к 500.   -  person Jaroslaw Pawlak    schedule 16.11.2015
comment
Есть ли встроенный маппер в jersey для NotFoundException? конструктор NotFoundException делает это super (Responses.notFound (). entity (message) .type (text / plain) .build ()); Это причина, по которой я получаю ответ в виде обычного текста?   -  person dk_123    schedule 16.11.2015
comment
Наверняка. Вы всегда можете создать собственное NotFoundException, расширяющее исключение WebApplicationException. Вы можете просто сделать любой ответ в конструкторе. Таким образом, вам не понадобится картограф. Если вы все еще хотите, чтобы он проходил через картограф (возможно, для ведения журнала), просто не расширяйте WebApplicationException   -  person Paul Samsotha    schedule 16.11.2015
comment
Спасибо! Я тоже думаю, что мне нужно создать собственное исключение. Я использовал другой конструктор NotFoundException, и он сработал !! Но я не мог получить желаемое сообщение в 'строке', я могу получить только URI ресурса   -  person dk_123    schedule 16.11.2015
comment
В Jersey 2.x, если вы выбрасываете исключение WebApplicationException с ненулевым объектом в ответе, оно не будет обнаружено картографом. javax.ws.rs.NotFoundException расширяет исключение WebApplicationException. Не устанавливайте enitty перед тем, как бросить его.   -  person Filip    schedule 16.11.2015
comment
@peeskillet правильный. Проблема в том, что ExceptionMapper не запускается, когда генерируется исключение WebApplicationException, содержащее объект. Похоже на ошибку   -  person ChrisO    schedule 16.11.2017


Ответы (1)


Фрагмент из трикотажа ServerRuntime класса. В нем есть особая логика, согласно которой, если Exception является экземпляром WebApplicationException и имеет тело, он вообще не переходит в средства отображения исключений.

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);
}
person Sunny Agarwal    schedule 25.05.2018