Chris
Chris

Reputation: 85

Omnifaces FullAjaxExceptionHandler support on SAP Netweaver Java

My Issue: I'm not certain, but I believe there is an SAP provided authentication Servlet Filter, redirecting to the SAP default logon page (which of course is causing a problem since it isn't returning an xml response), which is making the FullAjaxExceptionHandler to not be invoked. I'm looking for help in determining what the root cause really is, or if there are any alternatives to fix it.

My environment:

Background:

I have a sample application which has session-config session-timeout set to 1 minute, and have the Omnifaces FullAjaxExceptionHandlerFactory configured in 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>
...

The way I've determined Netweaver works, is it will mark the session as "expired" after one minute, but the session itself is not cleaned up immediately (I understand this is common in web containers). If I submit an ajax request after the session expired but before the session is completely removed by the server, the FullAjaxExceptionHandler kicks in, and properly displays my View Expired page. If however the server has already cleaned up the expired session, nothing happens, and the page appears "dead" until a physical refresh is performed.

From reading many answers by @balusc, I suspect that an SAP provided http filter is kicking in, which is redirecting the ajax request to the SAP login page, which is why the application isn't working.

Is there any way of determining for sure what is causing it? If it is a server provided filter, is there anyway to override it?

Upvotes: 1

Views: 194

Answers (1)

Chris
Chris

Reputation: 85

Yet again, thanks BalusC! You pushed me in the right direction.

SAP Netweaver has a global-web.xml file which defines some default functionality. One of them is as follows:

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

So what I did was used the same <filter-name> in my own web.xml, providing a class which extends SAP's Authentication Filter.

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

Since the <filter-name> is the same, the one defined in my local web.xml wins.

Here is my 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);
    }
}

Upvotes: 1

Related Questions