SAP Netweaver 上的 Omnifaces FullAjaxExceptionHandler 支持 Java

Omnifaces FullAjaxExceptionHandler support on SAP Netweaver Java

我的问题: 我不确定,但我相信有一个 SAP 提供的身份验证 Servlet 过滤器,重定向到 SAP 默认登录页面(这当然会导致问题,因为它没有返回 xml 响应),这是使 FullAjaxExceptionHandler 不被调用。我正在寻求帮助以确定真正的根本原因是什么,或者是否有任何替代方法可以解决它。

我的环境:

背景:

我有一个示例应用程序,其中 session-config session-timeout 设置为 1 分钟,并且在 faces-config.xml.

中配置了 Omnifaces FullAjaxExceptionHandlerFactory

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>
... 

人脸-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 工作的方式是,它会在一分钟后将会话标记为 "expired",但会话本身不会立即清理(我知道这在 Web 容器中很常见)。如果我在会话过期后但在会话被服务器完全删除之前提交 ajax 请求,FullAjaxExceptionHandler 将启动,并正确显示我的“查看已过期”页面。但是,如果服务器已经清除了过期的会话,则什么也不会发生,页面会显示 "dead",直到执行物理刷新。

通过阅读@balusc 的许多答案,我怀疑 SAP 提供的 http 过滤器正在启动,它将 ajax 请求重定向到 SAP 登录页面,这就是应用程序无法运行的原因.

有什么方法可以确定是什么原因造成的吗?如果它是服务器提供的过滤器,是否可以覆盖它?

再次感谢 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>

所以我所做的是在我自己的 web.xml 中使用相同的 <filter-name>,提供 class 扩展 SAP 的身份验证过滤器。

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

由于<filter-name>相同,所以我本地web.xml中定义的那个胜出。

这是我的 class:

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);
    }
}