Popup messages are not displayed after redirecting to MyFaces while it was working in Moharra
I have my own ExceptionHandlerWrapper to handle ViewExpiredException and other errors.
The idea is to catch the error, add an error message, and redirect (with a redirect, not a navigation) to the index page where the error message will be displayed.
fc.getExternalContext().getFlash().setKeepMessages(true);
Messages.addFlashError(null, "my message");
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("foo", "hello");
fc.getExternalContext().redirect("index.xhtml");
However, flash messages are not saved (but foo is present in the flash area).
This worked in mojarra, but I upgraded to myfaces 2.2.4 and it stopped working. Any ideas? (also using symbols 1.8.1) Thanks.
source to share
I looked at the source for MyFaces and it seems that they clearly need an additional call Flash#setRedirect()
on top Flash#setKeepMessages()
. While the Javadoc is admittedly not crystal clear on this one, I would expect the call to setRedirect(true)
be only needed for Flash attributes, not Flash messages, which has its own call setKeepMessages(true)
.
So, basically, you should do the following:
fc.getExternalContext().getFlash().setKeepMessages(true);
Messages.addFlashError(null, "my message");
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("foo", "hello");
fc.getExternalContext().getFlash().setRedirect(true); // <-- Add this.
fc.getExternalContext().redirect("index.xhtml");
However, since you are already using the JSF OmniFaces utility library , which already implicitly calls setKeepMessages(true)
when you use Messages#addFlashXxx()
, and also implicitly calls setRedirect(true)
when you use Faces#redirect()
, you can get away with just the following, which does the same as the "mess" above:
Messages.addFlashGlobalError("my message");
Faces.setFlashAttribute("foo", "hello");
Faces.redirect("index.xhtml");
No need for custom phase audition.
source to share
I have temporarily solved this with PhaseListener. I don't like it but it works now
What i do when i add flash message i also put it in flash area:
Messages.addFlash(null, new FacesMessage(severity, summary, detail));
context.getExternalContext().getFlash().put("messages", context.getMessageList());
Then I restore them to the phase sheet
public void beforePhase(final PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
if (!facesContext.getResponseComplete()) {
this.restoreMessages(facesContext);
}
}
}
private int restoreMessages(final FacesContext facesContext) {
final Object flash = facesContext.getExternalContext().getFlash().get("messages");
if (flash != null) {
List<FacesMessage> messages = (List<FacesMessage>) flash;
int restoredCount = messages.size();
for (Object element : messages) {
facesContext.addMessage(null, (FacesMessage) element);
}
return restoredCount;
}
return 0;
}
source to share