Ответ 1
Это связано с тем, что ViewExpiredException
завернут в ServletException
в соответствии со спецификацией JSF. Здесь выдержка из главы 10.2.6.2 спецификации JSF 1.2:
10.2.6.2 FacesServlet
Вызвать метод
execute()
сохраненного экземпляраLifecycle
, передавFacesContext
экземпляр для этого запроса в качестве параметра. Если методexecute()
бросает aFacesException
, перебрасывает его какServletException
с помощьюFacesException
в качестве основной причины.
Как распределяются страницы ошибок, указан в спецификации API сервлета. Здесь выдержка из раздела 9.9.2 Спецификация API сервлета 2.5:
SRV.9.9.2 Страницы ошибок
Если объявление no
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()
в конструкторе или методе bean или так. Это, в свою очередь, обернулось бы в какое-то исключение EL. Вы можете в конечном итоге добавить строку отладки rootCause
в Filter
, чтобы увидеть ее самостоятельно.
Если вы используете Eclipse/Tomcat, быстрый способ протестировать ViewExpiredException
следующий:
- Создайте страницу JSF с помощью простой командной кнопки, разверните и запустите ее и откройте в веб-браузере.
- Вернитесь к Eclipse, щелкните правой кнопкой мыши Tomcat-сервер и выберите "Clean Tomcat Work Directory". Это перезапустит Tomcat и, чтобы удалить все сеансы сериализации (важно! Просто перезапустить Tomcat недостаточно).
- Вернитесь к веб-браузеру и нажмите кнопку с командой (без предварительной загрузки страницы заранее!).