I am new to JSF and I am working on handling session timeout for a JSF application. I am trying to get the code to work for ajax calls and not able to achieve that so far. I have tried two approaches:
Approach 1: SessionListener (for cleanup work) and SessionFilter (for filtering every request and checking if session timed out) My Code snippet for Filter:
if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// is session expire control required for this request? (not required for home page or timeout page or JSF resources)
if (isSessionControlRequired(httpServletRequest)) {
// is session invalid?
if (isSessionInvalid(httpServletRequest)) {
String timeoutUrl = httpServletRequest.getContextPath() + "/timeout.html";
logger.info("session is invalid! redirecting to timeoutpage : " + timeoutUrl);
//httpServletResponse.sendRedirect(timeoutUrl);
//final FacesContext facesContext = FacesContext.getCurrentInstance();
//final ExternalContext externalContext = facesContext.getExternalContext();
//externalContext.dispatch("/start.jsp");
RequestDispatcher rd = httpServletRequest.getRequestDispatcher("/timeout.html");
rd.forward(httpServletRequest, httpServletResponse);
return;
}
}
}
chain.doFilter(request, response);
Approach 2: CustomeExceptionHandler handling ViewExpiredException Code snippet of handle() :
for (final Iterator<ExceptionQueuedEvent> it = getUnhandledExceptionQueuedEvents().iterator(); it.hasNext();) {
Throwable t = it.next().getContext().getException();
while ((t instanceof FacesException || t instanceof ELException) && null != t.getCause()) {
t = t.getCause();
}
if (t instanceof ViewExpiredException) {
final FacesContext facesContext = FacesContext.getCurrentInstance();
final ExternalContext externalContext = facesContext.getExternalContext();
final Map<String, Object> requestMap = externalContext.getRequestMap();
NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
try {
final String viewId = ((ViewExpiredException) t).getViewId();
String message = "View has expired. " + viewId;
logger.error(message);
requestMap.put("errorMsg", message);
try {
requestMap.put("currentViewId", viewId);
nh.handleNavigation(facesContext, null, "/timeout.html");
facesContext.renderResponse();
// Force JSF to render the error page in its entirety to the ajax response.
//facesContext.setViewRoot(facesContext.getApplication().getViewHandler().createView(facesContext, "/timeout.html"));
//facesContext.getPartialViewContext().setRenderAll(true);
//facesContext.renderResponse();
//RequestContext rc = RequestContext.getCurrentInstance();
//rc.execute("addTitleDialog.show()");
//externalContext.dispatch("/start.jsp");
}
catch (final Exception e) {
logger.error("Cannot dispatch to /start.jsp");
}
facesContext.responseComplete();
}
finally {
it.remove();
}
}
else {
logger.error(t.getMessage(), t);
}
}
getWrapped().handle();
}
Both these approaches work for non-ajax POST calls but not for ajax calls. When I run my app in debug mode, I can step through all the statements for ajax calls also, which gives me an idea that the control does come to my code, executes it but for some reason, nothing happens on the UI. I have been trying to redirect user to a timeout page but the ideal thing would be to display a JSF dialog and upon hitting 'OK' take user to Home Screen (My app does not have a login screen.) I have a basic questions also, is view expiring exactly same as session timeout?
Any help would be much appreciated, thanks, Swati.