Игнорирование страницы с ошибкой web.xml с помощью команды "Джерси Экзекьютер"

@Provider
public class JerseyExceptionMapper implements ExceptionMapper<JerseyException> {


    @Override
    public Response toResponse(JerseyException jerseyException) {
        return Response.status(jerseyException.getErrorCode()).
                entity(jerseyException.getJsonResponseObj()).
                type(MediaType.APPLICATION_JSON).
                build();
    }

}

Приведенный выше код имеет нежелательные результаты при использовании компонента <error-page> в web.xml. Например, если мой Response.status установлен в 400, а мой error-page компонент определяет <error-code> из 400, веб-сервер перенаправляет запрос в местоположение, определенное в web.xml.

Это явно не то, что я хочу для запросов REST. Я прочитал еще одно сообщение в StackOverflow, в котором говорится, что причина, по которой запрос переадресовывается в error-page, происходит потому, что установлен HttpServletResponse.sendError(400). Этот пост сказал, что если вы установите вместо HttpServletResponse.setStatus(400), error-page будет проигнорирован.

Если это так, я не вижу, как это полезно, поскольку я не реализовал код Джерси. Опция, которую я вижу, заключается в том, чтобы исследовать исходный код класса Response и, возможно, повторно реализовать метод статуса или, возможно, другой код Джерси. Есть ли простой вариант здесь или что-то, что мне не хватает?

По сути, мой вопрос: учитывая, что я использую Джерси для REST, и я использую страницу с ошибками в своем web.xml, как я могу использовать вышеуказанный код, игнорируя только код error-page только для Джерси? Любой другой код, вызывающий ошибки HTTP, должен перейти в error-page. Или есть другое решение, которое не включает error-page, но будет работать идентично тому, что я хочу?

Ответ 1

Я могу воспроизвести проблему, но только если я передаю null как содержимое сущности.

Пример:

return Response.status(400)
        .entity(null)
        .type(MediaType.APPLICATION_JSON)
        .build();

или даже

return Response.status(400)
        .type(MediaType.APPLICATION_JSON)
        .build();

Оба будут приводить к перенаправлению на страницу с ошибкой, которая настроена для кода статуса HTTP 400, потому что контейнер будет использовать sendError(), если не указано содержание сообщения.

Но если вы сделаете это так:

return Response.status(400)
        .entity("An error occured.")
        .type(MediaType.APPLICATION_JSON)
        .build();

или это:

return Response.status(400)
        .entity("")
        .type(MediaType.APPLICATION_JSON)
        .build();

контейнер/трикотаж будет использовать метод setStatus() и не перенаправляется на страницу с ошибкой. Как указано в документах:

Этот метод используется для установки кода возврата, когда нет (например, для статуса SC_OK или SC_MOVED_TEMPORARILY коды).

Если этот метод используется для установки кода ошибки, то контейнер механизм страницы ошибки не будет запущен. Если есть ошибка и вызывающий объект хочет вызвать страницу ошибки, определенную в сети приложение, тогда необходимо использовать sendError (int, java.lang.String) вместо этого.

Итак, в вашем случае проблема заключается в том, что jerseyException.getJsonResponseObj() возвращает null. Чтобы избежать этого, вы должны выполнить проверку нулевого значения.

Существует ошибка JERSEY-1557 для Jersey 1.x, которая описывает проблему, она была закрыта без исправления, но с рекомендацией используйте пустую строку сущности в качестве обходного пути.
Существует также аналогичная ошибка, открытая для Jersey 2.x: JERSEY-2673

См. также: