I am pulling my hairs over it and i know it was discussed here millions times.. after reading dozens questions here regarding this topic and trying them.. result is still same, this exception is not handled and not redirected to my custom error page.
So first what i did i added this to my web.xml
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/errorpages/expired.xhtml</location>
</error-page>
and created this simple error page in path /errorpages/expired.xhtml
<ui:composition
template="/templates/common/base.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:define name="title">DeviceRepair - Sesja Wygasła</ui:define>
<ui:define name="metas">
<meta http-equiv="refresh" content="0;url=#{request.contextPath}/login.xhtml" />
</ui:define>
<ui:define name="content">
<h1>Sesja wygasła..</h1>
<h3>Zostaniesz wkrótce przekierowany do strony logowania.</h3>
<p><a href="#{request.contextPath}/login.xhtml">
Naciśnij tutaj jeżelili przekierowanie nie zaskoczyło lub jeżeli jesteś niecierpliwy
<!--Click here if redirect didn't work or when you're impatient-->
</a>.</p>
</ui:define>
</ui:composition>
It didnt worked.. so then I created custom exception handler like follows, factory
public class ExceptionHandlerFactory extends javax.faces.context.ExceptionHandlerFactory {
private javax.faces.context.ExceptionHandlerFactory parent;
public ExceptionHandlerFactory(javax.faces.context.ExceptionHandlerFactory parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler result = parent.getExceptionHandler();
result = new ViewExpiredExceptionHandler(result);
return result;
}
}
and custom wrapper class
public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler parent;
public ViewExpiredExceptionHandler(ExceptionHandler parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getWrapped() {
return this.parent;
}
@Override
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents()
.iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context =
(ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
if (t instanceof ViewExpiredException) {
ViewExpiredException vee = (ViewExpiredException) t;
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = facesContext.getExternalContext()
.getRequestMap();
NavigationHandler navigationHandler = facesContext.getApplication()
.getNavigationHandler();
try {
// Push some useful stuff to the request scope for use in the page
requestMap.put("currentViewId", vee.getViewId());
navigationHandler.handleNavigation(facesContext, null, "/errorpages/expired");
facesContext.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
}
and putted this to faces-config.xml
<factory>
<exception-handler-factory>
pl.blabla.devicerepair.exception.ExceptionHandlerFactory
</exception-handler-factory>
</factory>
Then it still didnt worked, so i added this to web.xml
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
Still same result, so changed javax.faces.PROJECT_STAGE in web.xml from Development to Production.. and it just ate error without any redirecting.. so even worse.
I test it by setting this in my web.xml
<session-config>
<session-timeout>
1
</session-timeout>
</session-config>
and after run web app, just wait 2 minutes, and click some command button. Thanks for any help.