I find this article to be useful for non-ajax request How to handle session expiration and ViewExpiredException in JSF 2? but I can't make use of this when I am submitting using an AJAX call.
Suppose in a primefaces dialog, I am making a post request using AJAX and session has already timed out. I see my page getting stuck.
How to fix this kind of scenario such that when I post using AJAX, I could redirect him to my view expired page and then forward him to the login page similar to the solution in the link above?
JSF2/Primefaces/Glassfish
To handle the exception whenever the user invokes a synchronous POST request on a page while the HTTP session has been expired and the JSF view state saving method is set to server , add an <error-page> to the web. xml which catches the JSF ViewExpiredException and shows the home page.
Ajax Attributes It is used to process in partial request. Immediate. false. boolean. It returns a boolean value that determines the phaseId, when true actions are processed at apply_request_values, when false at invoke_application phase.
Exceptions which are thrown during ajax requests have by default totally no feedback in the client side. Only when you run Mojarra with project stage set to Development
and use <f:ajax>
, then you will get a bare JavaScript alert with the exception type and message. But other than that, and in PrimeFaces, there's by default no feedback at all. You can however see the exception in the server log and in the ajax response (in the webbrowser's developer toolset's "Network" section).
You need to implement a custom ExceptionHandler
which does basically the following job when there's a ViewExpiredException
in the queue:
String errorPageLocation = "/WEB-INF/errorpages/expired.xhtml"; context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation)); context.getPartialViewContext().setRenderAll(true); context.renderResponse();
Alternatively, you could use the JSF utility library OmniFaces. It has a FullAjaxExceptionHandler
for exactly this purpose (source code here, showcase demo here).
A merge between the answer of @BalusC and this post, I solved my problem!
My ExceptionHandlerWrapper:
public class CustomExceptionHandler extends ExceptionHandlerWrapper { private ExceptionHandler wrapped; CustomExceptionHandler(ExceptionHandler exception) { this.wrapped = exception; } @Override public ExceptionHandler getWrapped() { return wrapped; } @Override public void handle() throws FacesException { final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); while (i.hasNext()) { ExceptionQueuedEvent event = i.next(); ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); // get the exception from context Throwable t = context.getException(); final FacesContext fc = FacesContext.getCurrentInstance(); final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap(); final NavigationHandler nav = fc.getApplication().getNavigationHandler(); //here you do what ever you want with exception try { //log error ? //log.log(Level.SEVERE, "Critical Exception!", t); if (t instanceof ViewExpiredException) { requestMap.put("javax.servlet.error.message", "Session expired, try again!"); String errorPageLocation = "/erro.xhtml"; fc.setViewRoot(fc.getApplication().getViewHandler().createView(fc, errorPageLocation)); fc.getPartialViewContext().setRenderAll(true); fc.renderResponse(); } else { //redirect error page requestMap.put("javax.servlet.error.message", t.getMessage()); nav.handleNavigation(fc, null, "/erro.xhtml"); } fc.renderResponse(); // remove the comment below if you want to report the error in a jsf error message //JsfUtil.addErrorMessage(t.getMessage()); } finally { //remove it from queue i.remove(); } } //parent hanle getWrapped().handle(); } }
My ExceptionHandlerFactory:
public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory { private ExceptionHandlerFactory parent; // this injection handles jsf public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) { this.parent = parent; } @Override public ExceptionHandler getExceptionHandler() { ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler()); return handler; } }
My faces-config.xml
<?xml version='1.0' encoding='UTF-8'?> <faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"> <factory> <exception-handler-factory> your.package.here.CustomExceptionHandlerFactory </exception-handler-factory> </factory> </faces-config>
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