当前位置: 首页 > 知识库问答 >
问题:

为什么GlassFish 4不验证我的@Valid@ElementCollection字段的成员?

司空皓
2023-03-14

我创建了以下实体并可嵌入:

@Entity
public class Person implements Serializable {

    @NotNull
    @Pattern(regexp = "([A-Z][a-z]*)*", message = "First Name must match pattern ([A-Z][a-z]*)*")
    private String firstName;

    @Valid
    @ElementCollection
    private List<Email> email;
...
}

@Embeddable
public class Email implements Serializable {

    @NotNull (message = "Email Address may not be null")
    @Pattern(regexp = "[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}", message = "Email Address must match pattern [-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}")
    private String address;
...
}

然后,我使用PersonCreater.xhtml JSF页面和PersonManager无状态会话EJB测试了GlassFish4/Hibernate Validator5.0.0级联验证功能,如下所示:

  1. 创建的人。
  2. 将地址为“ADSJ ALKJDFA”的电子邮件添加到人员电子邮件列表。
  3. 将地址为“#AV@#$R”的电子邮件添加到人员电子邮件列表。
  4. 保留了对象。

不幸的是,我没有收到任何错误,带有无效电子邮件地址的Person对象被持久化到数据库中。

作为测试,我将Person类上的email属性从电子邮件列表更改为单个电子邮件,如下所示。

@Entity
public class Person implements Serializable {

    @Valid
    private Email email;
...
}

然后我执行了以下测试。

  1. 创建的人。
  2. 将地址为“ADSJ ALKJDFA”的电子邮件添加到人员电子邮件列表。
  3. 保留了对象。
    Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    Set<ConstraintViolation<Email>> emailCV = validator.validate(newEmail);
    logger.debug("Email constraint violations: " + emailCV);

    Set<ConstraintViolation<Person>> personCV = validator.validate(person);
    logger.debug("Person constraint violations: " + personCV);

    Set<ConstraintViolation<Person>> personEmailCV = validator.validateProperty(person, "email");
    logger.debug("Person Email constraint violations: " + personEmailCV);
  • 电子邮件约束冲突:[ConstraintViolationImpl{InterpolatedMessage=“电子邮件地址必须匹配模式...
  • 人员约束冲突:[ConstraintViolationImpl{InterpolatedMessage=“电子邮件地址必须匹配模式...
  • 人员电子邮件约束违规:[]

我希望validator.validate(newEmail);方法调用会引发模式冲突,因为我正在验证newEmail本身。

但是,我没有想到validator.validate(person);方法调用会发现模式冲突,因为我认为我的问题与我的实体和可嵌入类有关。

这些结果告诉我,我已经正确配置了实体和可嵌入类,但是由于某种原因,GlassFish在使用JSF页面创建Person或者使用EJB保存Person时不会自动验证email属性。

我需要配置GlassFish来自动执行级联验证吗?

最后,我不知道为什么validator.validate(person);方法调用发现了模式冲突,而validator.validateProperty(person,“email”);方法调用没有发现。

下面是我的persistence.xml中的persistence-unit。

<persistence-unit name="ELISPU" transaction-type="JTA">

    <jta-data-source>jdbc/elis</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>

    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="create" />
    </properties>

</persistence-unit>

以下是my Person类的更完整视图:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQueries({
        @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p ORDER BY p.lastName, p.firstName"),
        @NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE p.lastName = :lastName and p.firstName = :firstName and p.middleName = :middleName"),
        @NamedQuery(name = "Person.findByShortName", query = "SELECT p FROM Person p WHERE p.shortName = :shortName") })
public class Person implements Serializable {

    final static Logger logger = LoggerFactory.getLogger(Person.class.getName());

    static final long serialVersionUID = 1L;

    @TableGenerator(name = "Person_Generator", table = "ID_Gen", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL", initialValue = 0, allocationSize = 1)
    @Id
    @GeneratedValue(generator = "Person_Generator")
    @XmlAttribute
    private Long id;
    @Version
    @XmlAttribute
    private Integer version;
    private String prefixName;
    @NotNull
    @Pattern(regexp = "([A-Z][a-z]*)*", message = "First Name must match pattern ([A-Z][a-z]*)*")
    private String firstName;
    @Pattern(regexp = "([A-Z][a-z]*)*", message = "Middle Name must match pattern ([A-Z][a-z]*)*")
    private String middleName;
    @NotNull 
    @Pattern(regexp = "([A-Z][a-z]*)*", message = "Last Name must match pattern ([A-Z][a-z]*)*")
    private String lastName;
    private String suffixName;
    @NotNull
    @Pattern(regexp = "([A-Z][a-z]*)*", message = "Familiar Name must match pattern ([A-Z][a-z]*)*")
    private String familiarName;
    @NotNull
    @Column(unique = true)
    @Pattern(regexp = "[a-z0-9]*", message = "Short Name must match pattern [a-z0-9]*")
    private String shortName;
    private String description;

    @Valid
    @ElementCollection
    private List<Email> email;
    @ElementCollection
    private List<Voice> voice;
    @ElementCollection
    private List<Address> addresses;

    private ELISFile picture;
    @XmlElementWrapper(name = "notes")
    @XmlElement(name = "note")
    @ElementCollection
    private List<EntityNote> notes;
    @XmlTransient
    // @XmlElementWrapper(name="history")
    // @XmlElement(name="event")
    @NotNull
    @ElementCollection
    private List<EntityEvent> history;

    public Person() {

        logger.debug("Person created.");

        email = new ArrayList<Email>();
        voice = new ArrayList<Voice>();
        addresses = new ArrayList<Address>();
        notes = new ArrayList<EntityNote>();
        history = new ArrayList<EntityEvent>();

    }
...

以下是我的Email类更完整的版本:

@Embeddable
@XmlAccessorType(XmlAccessType.FIELD)
public class Email implements Serializable {

    final static Logger logger = LoggerFactory.getLogger(Email.class.getName());

    static final long serialVersionUID = 1L;

    @NotNull (message = "Email Type may not be null")
    @Enumerated(EnumType.STRING)
    private EmailType type;
    @NotNull (message = "Email Address may not be null")
    @Pattern(regexp = "[-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}", message = "Email Address must match pattern [-0-9a-zA-Z.+_]+@[-0-9a-zA-Z.+_]+.[a-zA-Z]{2,4}")
    private String address;
    private String description;
    ...

共有1个答案

西门良才
2023-03-14

问题不是Glassfish,而是您的模型以及JSF如何与Bean验证集成。您可能已经发现,JSF没有使用验证器#validte,而是使用验证器#validatePropery来验证单个属性上的约束。前者验证完整的对象图,而后者只验证给定属性上指定的约束。级联验证不由验证器#validateproperty执行。

不过,在JPA级别上的验证(如果您启用了它)应该可以工作。在不同的JPA生命周期回调中会出现完整的实体验证。

 类似资料:
  • 问题内容: 从JavaDoc: 验证此容器及其所有子组件。验证容器意味着布置其子组件。 那就是我想做的。使用尽可能轻巧的组件。但是当我这样做时,对的调用不会使组件“有效”。 为什么我不能做一个有效的? 问题答案: 在文档中说: 当组件在其父容器中的大小和位置正确且其所有子组件也均有效时,该组件才有效。 这种情况,直到你达到顶级容器(,或)。在您所遇到的问题的示例中,您没有父母,所以它永远不会有效。

  • 我有一个域名注册在AWS Route53与ACM证书。我现在试图将域名和证书都转移到一个新的帐户,以及用Terraform管理资源。我使用AWS CLI将域名移动到新的帐户,它似乎工作得很好。然后,我尝试运行这个Terraform代码为域创建一个新的证书和宿主区域。 这有两件事很奇怪。首先,创建了证书,但验证从未完成。它仍处于待定验证状态。我在失败后的某个地方读到,您不能自动验证,您需要手动创建C

  • 问题内容: 我有一个具有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示该bean和该bean都在创建,但是每当我尝试在服务bean上调用该方法时,都会得到一个a 。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 本文向大家介绍为什么我的Spring @Autowired字段为空?

  • 我想验证只有当另外两个输入为空时才需要输入。所以我使用required_without_all验证规则。 根据Laravel 5.4文件要求,无需所有: 只有当所有其他指定字段都不存在时,验证中的字段才必须存在且不为空。 然而,我认为我不知道现在是什么意思,因为我认为这意味着输入必须被填充。 当我在用户名为空的情况下运行测试时,无论firstname和lastname输入是否为空,它都会返回以下错

  • 我在Hibernate验证器和JSF中遇到了一些令人惊讶的行为。我想知道这种行为是一种错误,还是我对自己期望的一种误解。 我有这个Facelets页面: 如果在中运行方法,则验证器将始终返回验证错误(消息“可能不是空的”),因为始终为空。这种行为在我看来是正确的。 如果以空白值提交表单,则会收到“可能不为空”的错误消息;如果您输入了一个值,它将通过验证,但您将在控制台中看到的值仍然为NULL。这种

  • 问题内容: 我使用并且有以下内容; 验证说,但问题是该字段是 可选的 。因此,当用户将其留空时,也会显示相同的错误消息。 因此,我想做的是仅在字段不为空时验证。如果该字段为空,则跳过该字段的验证 问题答案: 我建议您不要使用,而是使用 主要原因是我们显示了要限制用户的一组值的消息,在此情况下,您的条件消息中显示了您不想限制的值。 因此,您想限制用户输入除空格和数字之外的其他任何内容,为此输入一个正