【问题标题】:Duplicated messages using Bean Validation with JSF and Omnifaces使用带有 JSF 和 Omnifaces 的 Bean Validation 重复消息
【发布时间】:2017-12-02 09:55:56
【问题描述】:

我在 JSF 2.2、Omnifaces 2.6.3 和 PrimeFaces 6.1 中遇到了客户端验证问题,导致来自 Bean Validation 的验证消息显示两次。

如果我在某个按钮中使用

<p:commandButton value="Some Action" ajax="false" action="#{someController.action}" validateClient="false"> <!-- validation disabled to test server side validation -->
     <o:validateBean value="#{someController.bean}" showMessageFor="@violating" />
</p:commandButton>

验证有效,但每次验证都会产生两条消息:

NotNull validation failed
NotNull validation failed
Max validation failed
Max validation failed

我发现问题出在类 javax.faces.validator.BeanValidator 上,它与 Omnifaces org.omnifaces.taghandler.ValidateBean 一起执行验证。。 p>

我试图删除 JSF 的默认 bean 验证,但 PrimeFaces 客户端验证依赖于启用将 validatorIds 发送到客户端,所以它不是一个选项。

我做了一个解决方法,在注释中使用一些组,默认 BeanValidator 不会验证,但我想知道是否有办法不强制使用组。

谢谢!

编辑: 示例项目https://github.com/marcelopio/duplicatederror

编辑 2:

SomeController.class

@Named
@ViewScoped
public class SomeController implements Serializable {

    private static final long serialVersionUID = 6184842672181799938L;

    private Foo foo = new Foo();

    public void someAction() {
        System.out.println("action");
    }

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

}

Foo.class

public class Foo implements Serializable {

    private static final long serialVersionUID = -7334434752280744719L;

    @Max(5)
    private Integer bar;

    public Integer getBar() {
        return bar;
    }

    public void setBar(Integer bar) {
        this.bar = bar;
    }

}

XHTML

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:o="http://omnifaces.org/ui">

    <h:head>
        <title>Teste</title>
    </h:head>

    <h:body>
        <h:form>
            <p:messages />
            <p:outputLabel value="Bar" for="bar"/>
            <p:inputText id="bar" value="#{someController.foo.bar}" />
            <p:message for="bar" />
            <p:commandButton value="Action" action="#{someController.someAction()}" ajax="false" validateClient="false">
                <o:validateBean value="#{someController.foo}" showMessageFor="@violating" />
            </p:commandButton>

        </h:form>
    </h:body>

</html>

WEB.XML

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
    <display-name>Duplicated Error</display-name>

    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>primefaces.TRANSFORM_METADATA</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>primefaces.CLIENT_SIDE_VALIDATION</param-name>
        <param-value>true</param-value>
    </context-param>

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>


    <welcome-file-list>
        <welcome-file>initial.xhtml</welcome-file>
    </welcome-file-list>

</web-app>

【问题讨论】:

  • 您好,欢迎来到 Stack Overflow,请花点时间通过 welcome tour 了解您在此处的方式(并获得您的第一个徽章),阅读如何创建 Minimal, Complete, and Verifiable example并检查How to Ask Good Questions,这样您就有机会获得反馈和有用的答案。也请添加someController的相关代码,以便更好地帮助您
  • 嗨!感谢您的回答,添加了演示项目
  • 如果您编写代码而不是共享指向它的链接,这是首选...提取与您的问题相关的部分,或与您遇到的错误相关的部分。请检查我提到的链接,因为其中提到了更多指南。
  • 我已经做到了,有意义的部分已经在问题上,控制器没有任何相关内容,也没有实际页面。我可以在这里添加完整的代码,它不会比已经发布的信息更有帮助。该链接就是证明。
  • @MarceloPiodeCastro:您没有发布任何显示消息的 xhtml/bean,也没有发布任何可能导致消息的输入,因此它不是有意义的部分。因此,始终请求minimal reproducible example。它还有助于缩小问题的范围。请做。

标签: java jsf primefaces omnifaces


【解决方案1】:

使用showMessageFor="" 属性控制消息的显示方式o:validateBean,同时还将p:messaagesglobalOnly 属性设置为true

更新

对于您的用例,o:messages 提供了这样做的可能性:

例如

<o:messages for="fooBar" />
<h:form id="fooBar">
      <p:outputLabel value="Bar" for="bar"/>
      <p:inputText id="bar" value="#{someController.foo.bar}" />
    <p:message for="bar" />
    <p:outputLabel value="Bar" for="foo"/>
      <p:inputText id="foo" value="#{someController.foo.bar}" />
    <p:message for="foo" />
</h:form>

如上所述,您可以在两个级别上显示您的消息。

【讨论】:

  • 嗨!感谢您的回答!但是我真的忘了添加一些信息。我想在 showMessageFor 中使用@violating,但问题仍然存在,还有其他建议吗?
  • globalOnly 不会在 p:messages 中显示任何消息,因为 @violating 会显示每个字段的消息。不过谢谢你的想法。问题是我需要同时显示 p:messages 和 p:message,所以我不能使用你的解决方案,但它可能对某人有用,所以我将它标记为已解决,只是我的用例没有。我会坚持我的小组解决方案。
  • 如果是这样的话,我建议你使用o:messages。我更新了答案以包含您的用例。
猜你喜欢
  • 2014-08-01
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 2011-12-28
  • 2017-06-10
  • 2017-07-17
相关资源
最近更新 更多