环境:JBoss EAP 6.3, Mojarra 2.1.28, JSF 2.0和java 1.7.0_79.
在我的xhtml模板中,我有两个p:消息,如下所示,用于显示全局消息:
<p:messages
id="globalMessages"
globalOnly="true"
autoUpdate="true"
severity="fatal, error, warn"
rendered="#{menuMB.renderFatalErrorWarningMessage}" />
<p:messages
id="globalMessagesInfo"
globalOnly="true"
autoUpdate="true"
severity="info"
rendered="#{menuMB.renderInfoMessage}" />
菜单中有
@Inject
private FacesContext facesContext;
public boolean isRenderInfoMessage() {
return facesContext.getMaximumSeverity() == null || facesContext.getMaximumSeverity().equals(FacesMessage.SEVERITY_INFO);
}
public boolean isRenderFatalErrorWarningMessage() {
return !isRenderInfoMessage();
}
在我使用模板的页面上,我有几个字段,它们各自的p:消息用于错误处理,例如
<h:inputText id="firstName" />
<p:message for="firstName" />
如果提交表单并且在字段firstName上验证失败,则按预期显示本地消息。然而,从这一刻起,ajax调用不再工作。
如果我改变MenuMB方法不使用FacesContext
public boolean isRenderInfoMessage() {
// return facesContext.getMaximumSeverity() == null || facesContext.getMaximumSeverity().equals(FacesMessage.SEVERITY_INFO);
return true;
}
public boolean isRenderFatalErrorWarningMessage() {
// return !isRenderInfoMessage();
return false;
}
,所有ajax调用都按预期工作。无论我从p:messages中删除渲染选项还是设置渲染=true/false(没有方法调用),都是一样的。
有什么办法解决这个问题吗?
您可能会发现某个地方正在发生异常,该异常正在停止所有未来的调用,很可能是潜在的java脚本问题。
同样根据记忆,你不需要在渲染标签中包装p:消息——它只会在你定义的指定严重性的内容中自动渲染。
目标呈现的一个问题是值必须已经在页面上才能被定位,所以定位一个可能不会被呈现的属性将会失败。最好将sed属性包装在另一个可以定位的标签中,然后它将加载内部内容渲染。
我发现解决我的问题的唯一方法是通过覆盖类MessagesRenderer从primefaces:
package xx.xx.xx.PFMessagesRenderer;
import org.primefaces.component.messages.MessagesRenderer;
public class PFMessagesRenderer extends MessagesRenderer {
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
Messages uiMessages = (Messages) component;
ResponseWriter writer = context.getResponseWriter();
String clientId = uiMessages.getClientId(context);
Map<String, List<FacesMessage>> messagesMap = new HashMap<String, List<FacesMessage>>();
////////////////////////////////////////
// BEGIN CHANGES
////////////////////////////////////////
boolean showInfoMessage = true;
if (uiMessages.isGlobalOnly()) {
Iterator<FacesMessage> messages = context.getMessages(null);
boolean hasInfoMessage = false;
boolean hasWarnErrorFatalMessage = false;
while (messages.hasNext()) {
if (messages.next().getSeverity().equals(FacesMessage.SEVERITY_INFO)) {
hasInfoMessage = true;
} else {
hasWarnErrorFatalMessage = true;
}
}
if (hasInfoMessage && hasWarnErrorFatalMessage) {
showInfoMessage = false;
}
}
////////////////////////////////////////
// BEGIN CHANGES
////////////////////////////////////////
String _for = uiMessages.getFor();
Iterator<FacesMessage> messages;
if (_for != null) {
messages = context.getMessages(_for);
} else {
messages = uiMessages.isGlobalOnly() ? context.getMessages(null) : context.getMessages();
}
while (messages.hasNext()) {
FacesMessage message = messages.next();
FacesMessage.Severity severity = message.getSeverity();
if (severity.equals(FacesMessage.SEVERITY_INFO)) {
////////////////////////////////////////
// BEGIN CHANGES
////////////////////////////////////////
if (showInfoMessage) {
addMessage(uiMessages, message, messagesMap, "info");
}
////////////////////////////////////////
// END CHANGES
////////////////////////////////////////
} else if (severity.equals(FacesMessage.SEVERITY_WARN)) {
addMessage(uiMessages, message, messagesMap, "warn");
} else if (severity.equals(FacesMessage.SEVERITY_ERROR)) {
addMessage(uiMessages, message, messagesMap, "error");
} else if (severity.equals(FacesMessage.SEVERITY_FATAL)) {
addMessage(uiMessages, message, messagesMap, "fatal");
}
}
writer.startElement("div", uiMessages);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("class", "ui-messages ui-widget", null);
for (String severity : messagesMap.keySet()) {
List<FacesMessage> severityMessages = messagesMap.get(severity);
if (severityMessages.size() > 0) {
encodeSeverityMessages(context, uiMessages, severity, severityMessages);
}
}
writer.endElement("div");
}
}
在faces-config.xml中我们需要添加
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.MessagesRenderer</renderer-type>
<renderer-class>xx.xx.xx.PFMessagesRenderer</renderer-class>
</renderer>
</render-kit>
这样我的模板页面就可以有一个单独的p:messages,如下所示:
<p:messages
id="globalMessages"
globalOnly="true"
autoUpdate="true"
severity="error, fatal, warn, info" />