I followed the following article to deal with ViewExpiredException -
Dealing Gracefully with ViewExpiredException in JSF2
It does what it is supposed to do. But I wanted to have some FacesMessage displayed on view if the user was redirected to it due to ViewExpiredException. So, I added a FacesMessage before redirection using NH.handlenaviage(). But it didn't work, and the reason was that the FacesMessage survived only one Request Processing Cycle.
At first my solution was to save the message in the session and retrieve it before Restore View phase of next cycle.
Even though it worked, I started looking for some standard solution and the first thing that I came across was the following article -
Persist and pass FacesMessages over multiple page redirects
But it didn't work. I think it's because the PhaseListeners are executed before ExceptionHandlers. So, in this case it was useless. I think it would have been useful if the exception handling code was executed before the afterPhase code of the listener.
Then I came across the following thread -
Preserving FacesMessage after redirect for presentation through in JSF
And the following is what I have right now -
@Override
public void handle() throws FacesException {
Iterator<ExceptionQueuedEvent> i = this.getUnhandledExceptionQueuedEvents().iterator();
while (i.hasNext()) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext eventContext = (ExceptionQueuedEventContext) event.getSource();
Throwable throwable = eventContext.getException();
if (throwable instanceof ViewExpiredException) {
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getExternalContext().getFlash().setKeepMessages(true);
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Your session expired!", null));
NavigationHandler nv = facesContext.getApplication().getNavigationHandler();
try {
facesContext.getViewRoot().setViewId("/login");
nv.handleNavigation(facesContext, null, "/login?faces-redirect=true");
facesContext.renderResponse();
} finally {
i.remove();
}
}
}
this.getWrapped().handle();
}
It took care of the problem but only for the views in the same directory.
And the following is what I got after some research on Flash scope -
FacesMessage not displayed on page in subdirectory
Can anybody help me on this one? I am looking for some JSF (if not standard then a good) way of handling this problem.
Thank you.
While I would still like to hear about how you (would) have taken care of this problem.
But the following is what I have done so far -
I just took the class in the article - Persist and pass FacesMessages over multiple page redirects
and moved the saveMessages()
and restoreMessages()
methods from MultiPageMessagesSupport
phase listener to a utility class (as static methods). And just call the those methods from the pase listener and (the saveMessages()
method) from the ViewExpiredExceptionHandler
after saving the faces messages in the faces context.
That takes care of the problem but it would be better to have some standard solution.