Это потому, что 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
заключается в следующем:
- Создайте страницу JSF с помощью простой командной кнопки, разверните и запустите ееи откройте его в веб-браузере.
- Вернитесь в Eclipse, щелкните правой кнопкой мыши сервер Tomcat и выберите Очистить рабочий каталог Tomcat .Это перезапустит Tomcat и и удалит все сериализованные сеансы (важно! Просто перезапустить Tomcat недостаточно).
- Вернитесь в веб-браузер и нажмите командную кнопку (без предварительной загрузки страницы!).