Сервлет обработчика ошибок: как получить причину исключения

В моем файле web.xml настроен сервлет ошибки:

<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/ExceptionHandler</location>
</error-page>

право?

В моем (в общем) сервлете:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        ...
        ...
    } catch (Exception e) {
        throw new ServletException("some mesage", e);
    }
}

Таким образом, "е" будет основной причиной в этом случае.

В моем классе ExceptionHandler у меня есть:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
    throwable.getCause() //NULL
}

это проблема. throwable.getCause() имеет значение null.

2 ответа

Решение

Если исключение, пойманное сервлетконтейнером, является ServletException и <error-page> объявлено, что ловит исключение, кроме ServletException, тогда его причина будет фактически развернута и сохранена как "javax.servlet.error.exception", Таким образом, у вас в основном уже есть как throwable переменная и вам не нужно звонить getCause() в теме.

См. Также 5-й абзац главы 9.9.2 спецификации Servlet 2.5:

Если нет error-page декларация, содержащая exception-type подходит с использованием сопоставления иерархии классов, и выбрасывается исключение ServletException или его подкласс, контейнер извлекает упакованное исключение, как определено ServletException.getRootCause метод. Второй проход выполняется над объявлениями страниц с ошибками, снова предпринимается попытка сопоставления с объявлениями страниц с ошибками, но вместо этого используется переносимое исключение.

Кстати, лучше использовать RequestDispatcher#ERROR_EXCEPTION константа вместо жесткого кодирования это.

Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

Редакция.

Хорошо, это может быть неправильно, у меня нет личного опыта работы с сервлетами обработки ошибок: вместо getCause() добавьте instanceofпроверьте ServletException, если оно прошло, приведите Throwable к ServletException и используйте getRootCause (). (BalusC, кажется, имеет лучшее решение для более новых версий Servlet API)

Посмотрите Исключения Без Первопричины для всестороннего обсуждения.

В более новых версиях Servlet API такой проблемы нет, но если вы используете какую-то старую версию ( 2.4 или более раннюю), вам также следует обновить свой код выдачи ServletException:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        ...
        ...
    } catch (Exception e) {
        ServletException se = new ServletException(e.getMessage(), e);
        se.initCause(e);
        throw se;
    }
}
Другие вопросы по тегам