jsfmessagemyfacesomnifacesflash-scope

Flash messages not shown after redirect in MyFaces while it worked in Mojarra


I've my own ExceptionHandlerWrapper to manage ViewExpiredException and other errors.

The idea is to catch the error, add some error message and redirect (with a redirection, not 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 stored (but foo is present in the flash scope).

This was working in mojarra, but I moved to myfaces 2.2.4 and it stopedd working. Any idea? (also using omnifaces 1.8.1) Thanks.


Solution

  • I looked at MyFaces source and it appears that they explicitly need an additional Flash#setRedirect() call on top of Flash#setKeepMessages(). Although the Javadoc is admittedly not crystal clear on this, I'd expect that calling setRedirect(true) is only necessary for Flash attributes, not for Flash messages, which has its own setKeepMessages(true) call.

    So, basically, you should be doing as follows:

    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, as you're already using JSF utility library OmniFaces, which already implicitly calls setKeepMessages(true) when you use Messages#addFlashXxx() methods, and also implicitly calls setRedirect(true) when you use Faces#redirect() method, you could get away with just the following which does exactly the same as above "mess":

    Messages.addFlashGlobalError("my message");
    Faces.setFlashAttribute("foo", "hello");
    Faces.redirect("index.xhtml");
    

    No need for a custom phase listener.