How to stack messages using the PrimeFaces message component?

I have a question regarding the p: messages component.

Firstly, here is my configuration:

  • PrimeFaces: 4.0.3 (elite)
  • JSF: MyFaces 2.0.2
  • Server: websphere 8.5.0.2

Then my code:

test.xhtml

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:fn="http://java.sun.com/jsp/jstl/functions"> <h:head> <f:facet name="first"> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </f:facet> <meta http-equiv="cache-control" content="no-store,no-cache" /> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="expires" content="0" /> </h:head> <h:body> <div id="content"> <h:form id="form1"> <p:tooltip/> <p:messages id="messages" showDetail="true" /> <p:remoteCommand async="true" autoRun="true" process="@this" partialSubmit="true" action="#{testBean.checkA}" /> <p:remoteCommand async="true" autoRun="true" process="@this" partialSubmit="true" action="#{testBean.checkB}" /> </h:form> </div> </h:body> </html> 

Test.java

 import java.io.Serializable; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.context.FacesContext; import org.primefaces.context.RequestContext; @ManagedBean(name="testBean") @ViewScoped public class Test implements Serializable { private static final long serialVersionUID = -1L; public void checkA() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Message 1", null)); RequestContext.getCurrentInstance().update("form1:messages"); } public void checkB() { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Message 2", null)); RequestContext.getCurrentInstance().update("form1:messages"); } } 

What this code does is very simple. When the page loads, two AJAX calls are made (checkA and checkB). I put Thread.sleep(2000) in checkA for testing purposes, since I want it to complete after checkB. Upon completion of the method, it sends a message to the user interface.

When I load the page, I see AJAX calls. CheckB will be completed first, so I will see “Message 2” on my page. But as soon as checkA is finished, the message is replaced with "Message 1". What I would like to do is add message "1" to "Message 2", so the user will see both messages on the screen. Is there a way to do this or is it a component limitation?

Secondly, as you can see in my code, I have to call RequestContext.getCurrentInstance().update("form1:messages"); to update my p:messages . If I delete this line of code and add autoUpdate="true" to the component, this will not work ...

One thing to consider, unfortunately, I can’t change the server configuration, because I don’t manage it, and there are already dozens of other applications on it.

Thanks in advance for your help!

+6
source share
2 answers

The problem is that FacesMessages Request Scoped . When you execute two ajax requests, when you reach the end of the second, the first message is not available at this moment.

You are using an @ViewScoped bean that stays alive until you leave the view, so the workaround should be in the form of a stack / queue in which messages are stored for display. When you think the last request has been completed, just add all your posts to FacesContext and clear the stack.

Another option would be to perform all your actions with the same method and display the messages you want after that. You would reduce network traffic by performing one request instead of two, but your choice seems interesting if you want to display certain parts of the page in front of others .

On the problem of updating, remember that you can specify the part of the form that you want to update directly on the page. Try adding update="messages" to the p:remoteCommand . About autoUpdate not working, maybe your remoteCommand partialSubmit attribute may carry you to the problem. Check out the definition of this attribute from the Primary Documents :

partialSubmit: Enables serialization of values ​​belonging to partially processed components only.

+3
source

You can use several p:message components:

 <p:message id="message1" for="message1ValidatorCall" /> <h:inputHidden id="message1ValidatorCall" value="message1ValidatorCall"> <f:validator validatorId="myValidator" /> </h:inputHidden> <p:message id="message2" for="message2ValidatorCall" /> <h:inputHidden id="message2ValidatorCall" value="message2ValidatorCall"> <f:validator validatorId="mySecondValidator" /> </h:inputHidden> 

You should consider faces validators if you want to check or check sth:

 @FacesValidator("myValidator") public class MyValidator implements Validator { @Override public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) throws ValidatorException { //validator logic } } 
+1
source

Source: https://habr.com/ru/post/957656/


All Articles