Reputation: 85
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
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