ViewExpiredException показано в java.lang.Throwable страница ошибки в web.xml
Я работаю над веб-приложением 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 ответ
Это потому что ViewExpiredException
был завернут вServletException
согласно спецификации JSF. Вот выдержка из главы 10.2.6.2 спецификации JSF 1.2:
10.2.6.2 FacesServlet
Позвоните
execute()
метод сохраненLifecycle
экземпляр, передаваяFacesContext
экземпляр для этого запроса в качестве параметра. Еслиexecute()
метод бросаетFacesException
Перекинь какServletException
сFacesException
в качестве основной причины.
Как распределяются страницы ошибок, указано в спецификации Servlet API. Вот выдержка из главы 9.9.2 спецификации 2.5 Servlet API:
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>
Обновление: согласно (удаленному) комментарию ФП: чтобы надежно проверить это, вы не можете сделать throw new ViewExpiredException()
в конструкторе бина или методе или так. Это, в свою очередь, будет включено в какое-то исключение EL. Вы можете в конечном итоге добавить отладочную линию печати rootCause
в Filter
увидеть это самостоятельно.
Если вы используете Eclipse/Tomcat, быстрый способ тестирования ViewExpiredException
является следующим:
- Создайте страницу JSF с помощью простой командной кнопки, разверните и запустите ее и откройте в веб-браузере.
- Вернитесь в Eclipse, щелкните правой кнопкой мыши сервер Tomcat и выберите " Очистить рабочий каталог Tomcat". Это перезапустит Tomcat и удалит все сериализованные сеансы (важно! Просто перезапустить Tomcat недостаточно).
- Вернитесь в веб-браузер и нажмите командную кнопку (без предварительной загрузки страницы!).
Как упоминалось BylusC, дескриптор развертывания не должен содержать какой-либо обработчик страницы ошибки, который будет перехватывать ViewExpiredException (заключенный внутри ServletException) вместо правильного - страницы ошибки для ViewExpiredException.
Не забудьте проверить, что дескриптор развертывания сервера (например, TomEE / conf / web.xml) не содержит определений страниц ошибок java.lang.Throwable или java.lang.Exception. Потому что эти два файла web.xml в основном объединены.
Да - файл web.xml приложения имеет приоритет над файлом web.xml сервера, но если файл web.xml приложения содержит
- страница ошибок для 500 (/error.xhtml)
и web.xml сервера для
- 500 (/500.html) и для
- Бросок (/bigerror.html)
тогда контекст приложения будет содержать слияние этих двух:
- 500 (/error.xhtml)
- Бросок (/bigerror.html)
и обработка ошибок ViewExpiredExcpetion не будет работать правильно.