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.

+3


source to share


2 answers


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.

+4


source


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;
}

      

0


source







All Articles