I have been looking at many posts on this topic but couldn't get a solution that works in my case.
I am using Java EE 6 with JSF 2.0 (deployed on JBoss AS 7.1)
In my web.xml
I have:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
and I want the user to be redirected to the login page when the session automatically times out.
what I have tried:
Approach 1: using filter
I have tried the following filter:
@WebFilter()
public class TimeOutFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
System.out.println("filter called");
final HttpServletRequest req = (HttpServletRequest) request;
final HttpSession session = req.getSession(false);
if (session != null && !session.isNew()) {
chain.doFilter(request, response);
} else {
System.out.println("Has timed out");
req.getRequestDispatcher("/logon.xthml").forward(request, response);
}
}
@Override
public void destroy() {
}
}
In the web.xml
I have tried
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
and
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
The filter works as it is called on every request (logging of "fiter called" in the console). However it is not called when the session times out.
Approach 2: HttpSessionLister
I have tried to use a HttpSessionListerner
. The method called having the following signature:
public void sessionDestroyed(HttpSessionEvent se) {
}
I wasn't able to redirect to a specific page. When I want to redirect a user I usually use the NavigationHandler
from the FacesContext
but in this case there is no FacesContext
(FacesContext.getCurrentInstance()
returns null
).
According to this post, the HttpListener cannot redirect the user because it is not part of a request.
Question
What is the best way to go to solve this problem? What can I do to make one of the two above-mentioned approaches to work?
You can't send a HTTP response as long as the client hasn't send a HTTP request. Simple as that. That's just how HTTP works. The Internet would otherwise have looked very different if any website was able to unaskingly push a HTTP response without the client having requested for it.
A JavaScript based heartbeat based on client's keyboard/mouse activity like as answered here, or a meta refresh
header like as answered here would be the solution if you've basically a single-page webapp (thus, you're effectively not using the session scope but the view scope), but that won't work nicely if you've the page open in multiple tabs/windows in the same session.
Websockets is in theory the right solution to push something to the client, but this requires in turn an active session. Chicken-Egg problem. Also, it wouldn't work in older browsers currently still relatively widely in use, so it should currently merely be used for progressive enhancement.
Your best bet is to just define an error page which deals with the case when the enduser invokes an action while the session is expired. See also javax.faces.application.ViewExpiredException: View could not be restored.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With