Пользовательский обработчик исключений JSF 2.0 - PullRequest
2 голосов
/ 12 марта 2011

Я изо всех сил пытаюсь понять, когда и как возникают исключения в JSF 2.0. Я искал решение дольше, чем хотел бы признать. В конечном счете, цель, которую я хочу достичь, - «обработать» необработанные исключения. Когда выдается исключение, я хочу иметь возможность собирать интересующую информацию об исключении и отправлять ее по электронной почте соответствующим администраторам сайта. Я выдвигаю ошибку, добавляя новое FacesException () в конструктор одного из моих компонентов поддержки. Я отлично работал в JSF 1.1, используя реализацию MyFaces. Я смог заставить это работать, обернув Жизненный цикл по умолчанию и просто переопределив методы execute () и render (). Я последовал за этим удивительным сообщением Hanspeter, чтобы заставить это работать:

"http://insights2jsf.wordpress.com/2009/07/20/using-a-custom-lifecycle-implementation-to-handle-exceptions-in-jsf-1-2/#comment-103"

Сейчас у меня обновление сайта до JSF 2.0 с использованием Mojarra. И все работает отлично, пока исключение выдается / перехватывается в методе execute (); в момент, когда я вхожу в render (), HttpServletResponse.isCommitted () равняется true, а фаза равна PhaseId RENDER_RESPONSE, что, конечно, означает, что я не могу выполнить перенаправление или пересылку. Я не понимаю, что изменилось между JSF 1.1 и 2.0 в отношении того, когда и как будет принят ответ. Как я уже говорил, у меня это отлично работает в рамках 1.1. После долгих поисков я обнаружил, что JSF 2.0 предоставляет отличный вариант для обработки исключений через Custom ExceptionHandler. Я следил за блогом Эда Бернса «Изящная работа с ViewExpiredException в JSF2»:

"http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2"

Как Эд указывает, что всегда есть путь web.xml путем определения тега и типа исключения / кода ошибки сервера и на какую страницу нужно отправить для сообщения об ошибке. Этот подход прекрасно работает, пока я ловлю 404 ошибки. Однако следует отметить одну интересную вещь: если я вызову ошибку 404, введя несуществующий URL-адрес, такой как / myApp / 9er, обработчик ошибок будет работать отлично, но как только я добавлю расширение «.xhtml» (т.е. / myApp / 9er.xhtml), тогда определение web.xml не обрабатывает его.

Одна вещь, которую я заметил, что Эд делал, что я не пробовал, это вместо того, чтобы пытаться сделать HttpServletRespone.sendRedirect (), он использует Navigationhandler.handleNavigation () для перенаправления пользователя на пользовательскую страницу ошибки. К сожалению, этот метод не сделал ничего отличного от того, что Faclets делает с ошибкой по умолчанию. Наряду с этим, конечно, я не смог сделать HttpServletResponse.sendRedirect () из-за тех же проблем, что были упомянуты выше; response.isCommitted () равно true.

Я знаю, что этот пост становится длинным, поэтому я сделаю небольшую заметку о попытке использовать PhaseListener для тех же целей. Я использовал следующие посты в качестве руководства, но этот маршрут все еще был неудачным:

"http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html"" http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html"

У всех и всех у меня такие же проблемы, как уже упоминалось. Когда выдается это исключение, ответ уже находится в фазе принятия, и я не могу перенаправить / перенаправить пользователя на стандартную страницу ошибки.

Я прошу прощения за такой длинный пост, я просто пытаюсь дать как можно больше информации, чтобы помочь устранить двусмысленность. У каждого есть какие-либо идеи / мысли для обхода, и мне любопытно, что может отличаться между JSF 1.1 и 2.0, что может привести к тому, что ответ будет зафиксирован, как только я войду в фазу render () жизненного цикла.

Спасибо огромное за любую помощь с этим !!!

Ответы [ 2 ]

3 голосов
/ 12 марта 2011

Таким образом, этот вопрос на самом деле касается не только обработчика пользовательских исключений (для которого JSF 2 обладает мощным механизмом ExceptionHandlerFactory), но и больше об отображении пользователю пользовательской страницы ошибок, когда ответ уже зафиксирован.

Один универсальный способ всегда иметь возможность перенаправить пользователя, даже если последний бит уже был записан в ответ, - использовать оболочку HttpServletResponse, которая буферизует заголовки и содержимое, записываемое в него.

Этодействительно имеет отрицательный эффект, что пользователь не видит, как страница постепенно создается.

Возможно, вы можете использовать эту технику только для захвата самого раннего коммита ответа, который, как кажется, делает JSF 2.0.Как только начинается ответ рендеринга, вы выводите заголовки, которые вы буферизировали до сих пор, и напрямую записываете содержимое ответа.

Таким образом, вы все равно сможете перенаправить пользователя на пользовательскую страницу ошибки, если произойдет исключение.до рендеринга ответа.

1 голос
/ 26 марта 2011

Я успешно реализовал фильтр, используя оболочку ответа, как описано выше, что позволяет избежать принятия ответа и позволяет перенаправлять на пользовательскую страницу даже при исключении в середине рендеринга страницы.

Оболочка ответа устанавливает собственный внутренний PrintWriter на StringWriter, который возвращается методом getWriter, чтобы вывод граней был буферизован.В «счастливом пути» фильтр впоследствии записывает внутреннее содержимое StringWriter в фактический ответ.В исключительной ситуации фильтр перенаправляет сообщение об ошибке jsp, которое записывает в (пока еще не принятый) ответ.

Для меня ключом к тому, чтобы избежать фиксации ответа, было перехват метода flushBuffer () (из ServletResponse, а не HttpServletResponse), и избегайте вызова super.flushBuffer ().Я подозреваю, что в зависимости от обстоятельств и, как отмечено выше, может также потребоваться переопределить некоторые другие методы, например, те, которые устанавливают заголовки.

...