如何在JSF中显示我的应用程序错误?

42
在我的JSF/Facelets应用程序中,这是我表单的一部分的简化版本:
<h:form id="myform">
  <h:inputSecret value="#{createNewPassword.newPassword1}" id="newPassword1" />
  <h:message class="error" for="newPassword1" />
  <h:inputSecret value="#{createNewPassword.newPassword2}" id="newPassword2" />
  <h:message class="error" for="newPassword2" />
  <h:commandButton value="Continue" action="#{createNewPassword.continueButton}" />
</h:form>

我希望能够基于continueButton()方法中发生的某些情况,将错误指派给特定的h:message标记。对于newPassword和newPassword2,需要显示不同的错误信息。验证器无法正常工作,因为将提供结果的方法(来自DB)在continueButton()方法中运行,并且运行两次的成本太高。

我不能使用h:messages标记,因为页面有多个位置需要显示不同的错误消息。当我尝试过这样做时,页面会重复显示每条消息。

我尝试了最佳猜测,但没有成功:

public Navigation continueButton() {
  ...
  expensiveMethod();
  if(...) {
    FacesContext.getCurrentInstance().addMessage("newPassword", new FacesMessage("Error: Your password is NOT strong enough."));
  }
}

我还缺少什么?任何帮助将不胜感激!

8个回答

61

FacesContext.addMessage(String, FacesMessage) 方法需要组件的clientId而不是它的id。如果你想知道为什么,可以考虑一个控件作为dataTable的子项,在每一行上使用相同的控件展示不同的值,这将导致每一行上显示不同的消息。而id总是相同的,clientId在每一行上是唯一的。

因此,"myform:mybutton" 是正确的值,但直接硬编码这个值是不明智的。查找方法可以减少视图和业务逻辑之间的耦合,并且也适用于像portlet等更严格的环境中。

<f:view>
  <h:form>
    <h:commandButton id="mybutton" value="click"
      binding="#{showMessageAction.mybutton}"
      action="#{showMessageAction.validatePassword}" />
    <h:message for="mybutton" />
  </h:form>
</f:view>

管理Bean逻辑:

/** Must be request scope for binding */
public class ShowMessageAction {

    private UIComponent mybutton;

    private boolean isOK = false;

    public String validatePassword() {
        if (isOK) {
            return "ok";
        }
        else {
            // invalid
            FacesMessage message = new FacesMessage("Invalid password length");
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(mybutton.getClientId(context), message);
        }
        return null;
    }

    public void setMybutton(UIComponent mybutton) {
        this.mybutton = mybutton;
    }

    public UIComponent getMybutton() {
        return mybutton;
    }
}

1
请认真阅读帖子,验证器模型无法应用于此情况。 - Eric Noob
更多关于使用客户端ID的内容:http://illegalargumentexception.blogspot.com/2009/02/jsf-working-with-component-ids.html - McDowell
@StudioWorks - UIComponent 实例是请求范围对象;将其注入会话范围对象中会导致范围泄漏。 - McDowell
好的,谢谢,但我的意思是是否有另一种使用@SessionScoped的替代方法。我该如何从视图中获取客户端ID? - StudioWorks

27

如果有人感兴趣,我能从你们所有的答复中找到了解决方案!

这是在 Facelet 中:

<h:form id="myform">
  <h:inputSecret value="#{createNewPassword.newPassword1}" id="newPassword1" />
  <h:message class="error" for="newPassword1" id="newPassword1Error" />
  <h:inputSecret value="#{createNewPassword.newPassword2}" id="newPassword2" />
  <h:message class="error" for="newPassword2" id="newPassword2Error" />
  <h:commandButton value="Continue" action="#{createNewPassword.continueButton}" />
</h:form>

这是在 continueButton() 方法中:

FacesContext.getCurrentInstance().addMessage("myForm:newPassword1", new FacesMessage(PASSWORDS_DONT_MATCH, PASSWORDS_DONT_MATCH));

太好了,它运行正常!感谢您的帮助!


6
您在调用addMessage()时还需要包含FormID。
 FacesContext.getCurrentInstance().addMessage("myform:newPassword1", new FacesMessage("Error: Your password is NOT strong enough."));

这应该能解决问题。
谢谢。

4
记住以下几点:

FacesContext context = FacesContext.getCurrentInstance();
context.addMessage( null, new FacesMessage( "The message to display in client" ));            

当第一个参数为null时,也是有效的,因为它将应用于整个表单。

更多信息: coreservlets.com //已过时


2

JSF是一个庞大的框架。也许我漏掉了什么,但我曾经通过将所需的消息保存到bean的属性中,并通过outputText显示属性来解决类似的问题:

<h:outputText
    value="#{CreateNewPasswordBean.errorMessage}"
    render="#{CreateNewPasswordBean.errorMessage != null}" />

我能理解这种方法的工作原理,但是肯定有更优雅的方式来处理错误信息! - Eric Noob
我必须承认,当我无法与h:message(s)和rich:message(s)交朋友时,我也曾经采取过同样的解决方法。 - activout.se

1
在谷歌搜索时找到了this。第二篇文章提到了JSF的不同阶段,这可能导致您的错误消息丢失。此外,尝试使用null代替“newPassword”,因为您没有使用id为“newPassword”的任何对象。

我知道它没有丢失,因为h:messages标签可以很好地输出错误信息... 我只是不知道如何将错误与特定的h:message标签绑定。更改id也没有帮助。 - Eric Noob

1
我尝试了最好的猜测,但没有成功:
在我看来,这看起来是正确的。您是否尝试过显式设置消息严重性?此外,我认为ID需要与组件的ID相同(即,如果那些是您的ID,则需要使用newPassword1或newPassword2,而不是示例中的newPassword)。
FacesContext.getCurrentInstance().addMessage("newPassword1", 
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error Message"));

然后使用<h:message for="newPassword1" />在JSF页面上显示错误消息。


0
简单的回答,如果您不需要将其绑定到特定组件...
Java:
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Authentication failed", null);
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, message);      

XHTML:

            <h:messages></h:messages>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接