FullAjaxExceptionHandler не перенаправляет на страницу с ошибкой после недействительного сеанса

У меня возникли проблемы с Omnifaces FullAjaxExceptionHandler (http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler). Он не перенаправляет на указанную страницу ошибки после того, как сеанс становится недействительным.

У меня в Faces-config есть следующее:

<factory>
    <exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>

И следующее в моем web.xml:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/pages/error/viewExpired.html</location>
</error-page>

После того, как я аннулирую сеанс, с точки зрения пользователя ничего не происходит. Приложение просто "мертвое". В моей консоли я вижу следующий запрос Ajax:

  • POST на исходную страницу Facelet с кодом ответа 302
  • GET на страницу входа с кодом 200 (но ничего не происходит, потому что это запрошено через Ajax)

Я использую MyFaces 2.1.10, Primefaces 3.5, Primefaces Extension 0.6.3 и Omnifaces 1.4.1 на WebLogic 12c.

Может ли кто-нибудь помочь мне в правильном направлении? Как заставить FullAjaxExeptionHandler работать правильно?

Спасибо


person Waterstraal    schedule 16.04.2013    source источник


Ответы (1)


POST на исходную страницу Facelet с кодом ответа 302

Это неправильно. Перенаправление на запрос JSF ajax должно иметь код ответа 200 со специальным ответом XML с элементом <redirect> с целевым URL-адресом в его атрибуте url.

Таким образом, это указывает на то, что вы вручную использовали HttpServletResponse#sendRedirect() где-то задолго до того, как у JSF появилась возможность справиться с ViewExpiredException.

Возможно, у вас где-то есть фильтр сервлета, который проверяет какой-то атрибут сеанса и отправляет перенаправление на основе его наличия/состояния? Затем этим фильтром следует управлять на основе следующего ответа: JSF Filter не перенаправлять After Initial Redirect, чтобы распознавать ajax-запросы JSF и возвращать специальный ответ XML вместо ответа 302.

E.g.

if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
    response.setContentType("text/xml");
    response.getWriter()
        .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
        .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
} else {
    response.sendRedirect(loginURL);
}

Все это совершенно не связано с FullAjaxExceptionHandler. У JSF не было возможности выдать ViewExpiredException, потому что вы уже сами отправляете перенаправление заранее.

person BalusC    schedule 16.04.2013
comment
Спасибо за Ваш ответ. Я уверен, что не отправляю перенаправление вручную... Может ли это быть конкретной проблемой weblogic? И можно ли написать свой собственный фильтр с вашим кодом реализации, чтобы исправить это? - person Waterstraal; 16.04.2013
comment
Да, это вполне может произойти, если вы используете аутентификацию, управляемую контейнером. Однако я недостаточно знаком с Weblogic, чтобы предложить правильное решение; OmniFaces имеет встроенное решение в OmniPartialViewContext, которое должно охватывать этот конкретный случай, однако оно работает только при выполнении перенаправления (как это делается Tomcat, JBoss и Glassfish) вместо перенаправления. В качестве первого шага изучите все атрибуты запроса, чтобы увидеть, не установил ли WebLogic какой-либо конкретный атрибут запроса, указывающий, что сработала аутентификация, управляемая контейнером. - person BalusC; 16.04.2013
comment
См. также этот связанный вопрос: /" title="viewexpiredexception не выдается по запросу ajax, если страница jsf защищена j se"> stackoverflow.com/questions/12504131/ - person BalusC; 16.04.2013
comment
Да, мы используем аутентификацию, управляемую контейнером. Означает ли это, что я не могу использовать FullAjaxExceptionHandler? Не могли бы вы указать мне направление, чтобы заставить это работать без использования вашего FullAjaxExceptionHandler? Заранее спасибо! - person Waterstraal; 16.04.2013
comment
Вы должны понимать, что ваша конкретная проблема совершенно не связана с FullAjaxExceptionHandler. У него даже не было возможности запуститься, потому что контейнер перенаправил ограниченный запрос на страницу входа по истечении сеанса. Это будет работать так, как вы ожидали, только если запрос не был заблокирован управляемой контейнером проверкой подлинности, потому что пользователь вышел из системы из-за истечения срока действия сеанса. - person BalusC; 16.04.2013
comment
Значит, единственный способ — не использовать аутентификацию, управляемую контейнером? - person Waterstraal; 16.04.2013
comment
Зависит от конкретных функциональных требований. С другой стороны, может быть и так, что вы просто ищете решение конкретной проблемы не в том направлении. FullAjaxExceptionHandler перехватывает только исключения, возникающие во время ajax-запросов JSF. В вашем конкретном случае нет никаких исключений. WebLogic перенаправил запрос на страницу входа, поскольку пользователь больше не вошел в систему. Даже если бы вы использовали обычный запрос вместо запроса ajax, вы все равно не получили бы ViewExpiredException и, таким образом, вообще никогда не попали бы в <error-page>. - person BalusC; 16.04.2013
comment
Я нашел решение - проблема была в FullAjaxExceptionHandler. Я заменил метод renderErrorPageView на `String viewId = getViewIdAndPrepareParamsIfNecessary(context, errorPageLocation); ViewHandler viewHandler = context.getApplication().getViewHandler(); Строка actionURL = viewHandler.getRedirectURL (контекст, viewId, null, false); context.getExternalContext().redirect(actionURL);` - person DCO; 30.07.2014
comment
@Dan: вы отправляете перенаправление HTTP вместо рендеринга представления. Это не соответствует стандартной спецификации сервлета и не работает для страниц ошибок в /WEB-INF. - person BalusC; 30.07.2014