Question

In a backing bean's @PostConstruct method, I make a call to an EJB which might return some messages that I want to display on the page via p:messages. However, even if I add the FacesMessages e.g. FacesContext.getCurrentInstance().addMessage(...), p:messages is not being updated with the FacesMessages.

If I instead invoke the call to the EJB on an action from the page (say a user clicks a button on the page which invokes a method that calls the EJB and then adds the FacesMessage(s)), then the messags show up using p:messages as expected.

How do I add Faces Messages during @PostConstruct and have them show up when the page is initially rendered?

Code:

Page1Controller.java:

@ManagedBean
public class Page1Controller
{
    @PostConstruct
    public void init()
    {
        FacesContext.getCurrentInstance().addMessage(null, 
            new FacesMessage("Test Message from @PostConstruct"));
    }

    public String getValue()
    {
            return "Some Value";
    }

    public void triggerMessage(ActionEvent event)
    {
            FacesContext.getCurrentInstance().addMessage(null, 
                    new FacesMessage("Test Message from Trigger Button"));      
    }

}

page1.xhtml

   <h:form>
        <p:messages showDetail="true" showSummary="true" autoUpdate="true"/>
        <h:outputText value="#{page1Controller.value}"/>
        <br/>
        <p:commandButton value="Trigger Message" 
                         actionListener="#{page1Controller.triggerMessage}"/>  
   </h:form>
Was it helpful?

Solution

That can happen when the message component is rendered before the message is added.

In your specific example, the bean is referenced for the first time by the <h:outputText> component and thus constructed for the first time at that moment. But the <h:outputText> component appears in your specific example after the <p:messages> component, so the <p:messages> component is already rendered and thus it's too late to show the message.

You need to make sure somehow that the message is added before the message component is rendered. One way is using <f:viewAction>. It runs during INVOKE_APPLICATION phase which is before RENDER_RESPONSE phase. Thus it runs before any component is rendered. A perfect opportunity thus.

<f:metadata>
    <f:viewAction action="#{bean.onload}" />
</f:metadata>

public void onload() {
    // Add message here instead of in @PostConstruct.
}

See also:

OTHER TIPS

You can collect the error and then display it at the end of loading the page using a remoteCommand of primefaces with autorun = true mode. In my case I have a viewScope and in xhtml I show the list of values that are loaded in the @PostConstruct. If an Exception is generated I will save it to the sample at the end of the page load if it exists using the remoteCommand.

private ArrayList<Exception> postConstucError = new ArrayList<>();

@PostConstruct
public void validarAcceso() {
    /**
     * verificar permisos a la vista de coeficientes
     */
    try {
            this.init() //load data;
        } catch (Exception e) {
        System.out.print(e.getMessage());
        this.postConstucError.add(e);
    }
}

 public void showPostConstructError() {
    try {
        for (int i = 0; i < this.postConstucError.size(); i++) {
            JsfUtil.addErrorMessage("Error al cargar datos iniciales: " + postConstucError.get(i).getMessage());
        }
    } catch (Exception e) {
        JsfUtil.addErrorMessage(e, "Error: showPostConstructError() " + e.getMessage());
    }
}

xhtml code

  <p:messages id="messages" showDetail="true" autoUpdate="true" closable="true"/> 
  <h:form>
        <p:remoteCommand id="rcomerror" name="showError" process="@this"  autoRun="true"
                         actionListener="#{mBPresentNinos.showPostConstructError()}" />  
    </h:form>

For me using preRenderView event to display message on form init was a messages-hell. So I created very simple "component" to keep static messages. For this example only one error message is supported.

staticMessage.xhtml:

<ui:fragment xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
             rendered="#{rendered}">
    <div id="staticMessage" class="ui-messages ui-widget" aria-live="polite">
        <div class="ui-messages-error ui-corner-all"><span class="ui-messages-error-icon"/>
            <ul>
                <li>
                    <span class="ui-messages-error-summary">#{value}</span>
                </li>
            </ul>
        </div>
    </div>
</ui:fragment>

Including messages:

 <ui:include src="/template/components/staticMessage.xhtml">
     <ui:param name="rendered"value="#{beanMB.staticMessagesRendered}"/>
     <ui:param name="value" value="Place your message here."/>
 </ui:include>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top