Поддержка Omnifaces FullAjaxExceptionHandler в SAP Netweaver Java

Моя проблема: я не уверен, но я полагаю, что есть предоставленный SAP фильтр сервлетов аутентификации, перенаправляющий на страницу входа SAP по умолчанию (что, конечно, вызывает проблему, поскольку он не возвращает xml), из-за чего FullAjaxExceptionHandler не вызывается. Я ищу помощи в определении того, что действительно является основной причиной, или если есть какие-либо альтернативы, чтобы исправить это.

Моя среда:

  • SAP Netweaver 7.4 (сервлет 2.5 с поддержкой JSF 2.1.x)
  • SAP JVM 6.1 (JVM SAP 1.6)
  • Мохарра 2.1.29
  • Омнифейс 1.11

Предыстория:

У меня есть пример приложения, в котором session-config session-timeout установлено значение 1 минута, а Omnifaces FullAjaxExceptionHandlerFactory настроен в faces-config.xml.

web.xml

...

<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/errorPage.xhtml</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/WEB-INF/viewExpired.xhtml</location>
</error-page>
<session-config>
    <session-timeout>1</session-timeout>
</session-config>
... 

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd" version="2.1">

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

То, как я определил, работает Netweaver, заключается в том, что он помечает сеанс как «истекший» через одну минуту, но сам сеанс не очищается немедленно (я понимаю, что это распространено в веб-контейнерах). Если я отправлю запрос ajax после истечения срока действия сеанса, но до того, как сеанс будет полностью удален сервером, сработает FullAjaxExceptionHandler и правильно отобразит мою страницу «Просмотр истекших». Однако, если сервер уже очистил сеанс с истекшим сроком действия, ничего не происходит, и страница выглядит «мертвой» до тех пор, пока не будет выполнено физическое обновление.

Прочитав множество ответов @balusc, я подозреваю, что срабатывает предоставленный SAP http-фильтр, который перенаправляет запрос ajax на страницу входа в SAP, поэтому приложение не работает.

Есть ли способ точно определить, что его вызывает? Если это фильтр, предоставленный сервером, можно ли его переопределить?


person Chris    schedule 15.09.2015    source источник
comment
Как выглядит ответ ajax в случае сбоя? Проверьте монитор HTTP-трафика браузера, чтобы увидеть его (нажмите F12 и откройте вкладку «Сеть»).   -  person BalusC    schedule 15.09.2015
comment
Ответ 200, и, как я подозреваю, это html из /logon, которая является общей страницей входа в систему. Так что это точно основная причина, есть ли какое-то решение?   -  person Chris    schedule 15.09.2015
comment
По сути, вам нужно сделать структуру аутентификации JSF ajax осведомленной. В OmniFaces есть встроенное исправление, но оно предназначено только для страницы входа, управляемой контейнером, как определено в <login-config><form-login-page>, а не для сторонних сред проверки подлинности. Вы можете найти в этом связанном/дублированном вопросе и ответе некоторые подсказки: /" title="fullajaxexceptionhandler не показывает страницу ошибки с истекшим сроком сеанса на кнопке ajax"> stackoverflow.com/questions/17296420/ Я не знаком с SAP, поэтому, к сожалению, не могу опубликовать подробный ответ для этого.   -  person BalusC    schedule 15.09.2015
comment
В Netweaver, если вы определяете <login-config> <auth-method>FORM</auth-method> </login-config> без элемента <form-login-page>, выполняется перенаправление на общую страницу входа в систему. Таким образом, это управляемый контейнером вход в систему, однако настроенный SAP. Мое предположение было (и теперь вы подтвердили), что мне нужно сделать его JSF ajax осведомленным, как вы говорите, но интересно, можно ли это сделать только путем переопределения предоставленного SAP фильтра, как вы сделали с примером Широ?   -  person Chris    schedule 15.09.2015
comment
Теоретически да. Ребята из SAP/Netweaver могут лучше всего ответить на этот вопрос. По сути, вам нужно где-то иметь крючок, с помощью которого вы могли бы манипулировать ответом, который должен привести конечного пользователя на страницу входа.   -  person BalusC    schedule 15.09.2015


Ответы (1)


Еще раз спасибо BalusC! Вы подтолкнули меня в правильном направлении.

SAP Netweaver имеет файл global-web.xml, который определяет некоторые функции по умолчанию. Один из них заключается в следующем:

<filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>com.sap.engine.services.servlets_jsp.server.servlet.AuthenticationFilter</filter-class>
</filter>

Итак, что я сделал, так это использовал тот же <filter-name> в моем собственном web.xml, предоставив класс, который расширяет фильтр аутентификации SAP.

<filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>com.example.AjaxAwareAuthenticationFilter</filter-class>
</filter>

Поскольку <filter-name> один и тот же, побеждает тот, который определен в моем локальном web.xml.

Вот мой класс:

package com.example;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.sap.engine.services.servlets_jsp.server.servlet.AuthenticationFilter;

public class AjaxAwareAuthenticationFilter extends AuthenticationFilter {
    @Override
    public void destroy() {
        super.destroy();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;

        HttpSession session = httpRequest.getSession(false);
        if (session == null && "partial/ajax".equals(httpRequest.getHeader("Faces-Request"))) {
                // JSF ajax request. Return special XML response which instructs
                // JavaScript that it should in turn perform a redirect.
                response.setContentType("text/xml");
                response.getWriter()
                    .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
                    .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>",
                            httpRequest.getContextPath());
        } else {
            super.doFilter(request, response, chain);
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        super.init(config);
    }
}
person Chris    schedule 16.09.2015