Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add FacesMessage during page load? Using @PostConstruct does not seem to work

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>
like image 982
BestPractices Avatar asked Apr 17 '12 18:04

BestPractices


2 Answers

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:

  • What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
like image 174
BalusC Avatar answered Nov 06 '22 23:11

BalusC


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>
like image 35
meyquel Avatar answered Nov 06 '22 22:11

meyquel