I have a question concerning the p:messages component.
First, here is my configuration:
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 really simple. When the page loads, two AJAX calls are made (checkA and checkB). I have put a Thread.sleep(2000)
in checkA for testing purpose as I want it to finish after checkB. Once a method is finished, it sends back a message to the UI.
When I load the page, I see both AJAX calls made. CheckB will be finished first, so I will see "Message 2" on my page. But as soon as checkA is finished, the message is replaced by "Message 1". What I would like to do is append "Message 1" to "Message 2", so the user will see both messages on the screen. Is there any way to do it or is it a limitation of the component?
Secondly, as you can see in my code, I have to call RequestContext.getCurrentInstance().update("form1:messages");
in order to see my p:messages
being updated. If I remove this line of code and add autoUpdate="true"
to the component, it doesn't work...
One thing to take into consideration, unfortunately, I cannot change the configuration of the server as I don't manage it and there are already dozens of other apps on it.
Thanks in advance for your help!
The problem you've here is that FacesMessages are Request Scoped. As you're performing two ajax requests, when you reach the end of the second one the first message is not available at that moment.
You're using a @ViewScoped
bean which remains alive till you leave the view itself, so the workaround should be having there a kind of stack/queue which stores the messages to display. When you consider the last request have been done, just add all your messages to the FacesContext
and clear the stack.
Other choice would be to perform all your operations in the same method and display the messages you want after that. You would decrease network traffic because of performing one request instead of two, but your choice seems interesting if you want to render specific parts of the page before other ones.
About your updating issue, remember you can specify the part of the form you want to update directly in the page. Try adding update="messages"
to your p:remoteCommand
tags. About autoUpdate
not working, possibly your remoteCommand
's partialSubmit
attribute could be carrying you on problems. Check out the definition of that attribute from Primefaces docs:
partialSubmit: Enables serialization of values belonging to the partially processed components only.
You can use multiple 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 validate sth:
@FacesValidator("myValidator")
public class MyValidator implements Validator {
@Override
public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) throws ValidatorException {
//validator logic
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With