in my preRender code for a page i add faces message then make navigation to another page as follows:
if(error){
addMessageToComponent(null,"AN ERROR HAS OCCURRED");
FacesContext.getCurrentInstance().getExternalContext().getFlash()
.setKeepMessages(true);
navigateActionListener("myoutcome");
}
and the util methods for adding message and navigation are:
public static String getClientId(String componentId)
{
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
UIComponent c = findComponent(root, componentId);
return c.getClientId(context);
}
public static UIComponent findComponent(UIComponent c, String id)
{
if (id.equals(c.getId())) { return c; }
Iterator<UIComponent> kids = c.getFacetsAndChildren();
while (kids.hasNext())
{
UIComponent found = findComponent(kids.next(), id);
if (found != null) { return found; }
}
return null;
}
/**
* @param componentId
* : the id for the jsf/primefaces component without formId:
* prefix. <br>
* if you use null then the message will be added to the
* h:messages component.
**/
public static void addMessageToComponent(String componentId, String message)
{
if (componentId != null)
componentId = GeneralUtils.getClientId(componentId);
FacesContext.getCurrentInstance().addMessage(componentId,
new FacesMessage(message));
}
public static void navigateActionListener(String outcome)
{
FacesContext context = FacesContext.getCurrentInstance();
NavigationHandler navigator = context.getApplication()
.getNavigationHandler();
navigator.handleNavigation(context, null, outcome);
}
but messages are not saved and so it doesn’t appear after redirect.
please advise how to fix that.
The
preRenderViewevent runs in the very beginning of theRENDER_RESPONSEphase. It’s too late to instruct theFlashscope to keep the messages. You can do this at the latest during theINVOKE_APPLICATIONphase.Since there’s no standard JSF component system event for this, you’d need to homebrew one:
To publish this, you need a
PhaseListener:After registering it as follows in
faces-config.xml:You’ll be able to use the new event as follows:
You only need to make sure that you’ve at least a
<f:viewParam>, otherwise JSF won’t enter the invoked phase at all.The JSF utility library OmniFaces already supports this event and the
preInvokeActionevent out the box. See also the showcase page which also demonstrates setting a facesmessage for redirect.