ViewExpiredException отображается в java.lang.Throwable ошибка страницы в web.xml - PullRequest
17 голосов
/ 08 июля 2010

Я работаю над веб-приложением JSF, в котором мне нужно вызвать страницу «Session Expired», если срок действия представления истекает, но страницу с общей технической ошибкой для всех остальных.Приложение переходит на страницу технической ошибки, когда я запускаю исключение.Вот определения страницы ошибки:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/jsps/utility/sessionExpired.jsp</location> 
</error-page> 
<error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/jsps/utility/technicalError.jsp</location> 
</error-page> 
<error-page>
    <error-code>500</error-code>
    <location>/jsps/utility/technicalError.jsp</location>
</error-page>

Я удалил элементы страницы ошибки technicalError.jsp, и она работала нормально, но когда я возвращаю их обратно, я не могу попасть на страницу sessionExpired.jsp.Как сообщить веб-контейнеру порядок оценки этих тегов, чтобы появилась нужная страница?Спасибо.

1 Ответ

16 голосов
/ 09 июля 2010

Это потому, что ViewExpiredException упакован в ServletException в соответствии со спецификацией JSF.Вот выдержка из главы 10.2.6.2 спецификации JSF 1.2 :

10.2.6.2 FacesServlet

Вызовите метод execute() сохраненного Lifecycle instance, передавая экземпляр FacesContext для этого запроса в качестве параметра.Если метод execute() выдает FacesException, , повторно выведите его как ServletException с FacesException в качестве основной причины .

Как страницы ошибокРаспределение указано в спецификации Servlet API.Вот выдержка из главы 9.9.2 Спецификация API сервлета 2.5 :

SRV.9.9.2 Страницы ошибок

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

В иерархии классов, ServletExceptionуже соответствует Throwable, поэтому его основная причина не будет извлечена для второго прохода.

Чтобы доказать это указанное поведение, замените javax.faces.application.ViewExpiredException на javax.servlet.ServletException на <exception-type> и повторите попытку.Вы увидите страницу ожидаемой ошибки.

Чтобы решить эту проблему, просто удалите страницу ошибки на java.lang.Throwable или java.lang.Exception.Если ни одна страница ошибки, относящаяся к конкретной исключительной ситуации, не соответствует, то она все равно будет возвращаться к странице с кодом ошибки 500.Итак, все, что вам нужно, это:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/jsps/utility/sessionExpired.jsp</location> 
</error-page> 
<error-page>
    <error-code>500</error-code>
    <location>/jsps/utility/technicalError.jsp</location>
</error-page>

Обновление : согласно (удаленному) комментарию OP: для надежного тестирования этого вы не можете сделать throw new ViewExpiredException()в конструкторе бина или методе или так.Это, в свою очередь, будет включено в какое-то исключение EL.В конечном итоге вы можете добавить строку отладки rootCause в Filter, чтобы увидеть ее самостоятельно.

Если вы используете Eclipse / Tomcat, быстрый способ тестирования ViewExpiredException заключается в следующем:

  1. Создайте страницу JSF с помощью простой командной кнопки, разверните и запустите ееи откройте его в веб-браузере.
  2. Вернитесь в Eclipse, щелкните правой кнопкой мыши сервер Tomcat и выберите Очистить рабочий каталог Tomcat .Это перезапустит Tomcat и и удалит все сериализованные сеансы (важно! Просто перезапустить Tomcat недостаточно).
  3. Вернитесь в веб-браузер и нажмите командную кнопку (без предварительной загрузки страницы!).
...