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

JSF结合Bean验证:ConstraintViolationException

温成济
2023-03-14

我尝试将JSF与Bean验证结合使用。基本上,一切正常,验证工作如预期,我得到了正确的消息,但我的Glassfish控制台上有一个例外:

Warnung:   EJB5184:A system exception occurred during an invocation on EJB MyEntityFacade, method: public void com.mycompany.testbv.AbstractFacade.create(java.lang.Object)
Warnung:   javax.ejb.EJBException
at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748)
....
....
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.

如果我使用自定义约束和预定义约束,则会发生此异常。

这是我的示例代码。

示例实体:

@Entity
@ValidEntity
public class MyEntity implements Serializable {

    private static final long serialVersionUID = 3104398374500914142L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Size(min = 2)
    private String name;

    public MyEntity(String name) {
        this.name = name;
    }

    public MyEntity() {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

自定义约束:

@Constraint(validatedBy = MyValidator.class)
@Target({FIELD, METHOD, TYPE})
@Retention(RUNTIME)
public @interface ValidEntity {
    String message() default "fail";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

自定义验证器:

public class MyValidator implements ConstraintValidator<ValidEntity, MyEntity>{

    @Override
    public void initialize(ValidEntity a) {
    }

    @Override
    public boolean isValid(MyEntity t, ConstraintValidatorContext cvc) {
        return false;
    }
}

样品控制器:

@Named
@SessionScoped
public class MyController implements Serializable {

    private static final long serialVersionUID = -6739023629679382999L;

    @Inject
    MyEntityFacade myEntityFacade;
    String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public void saveNewEntity() {
        try {
            myEntityFacade.create(new MyEntity(text));
        } catch (Exception e) {
            Throwable t = e;
            while (t != null) {
                if (t instanceof ConstraintViolationException) {
                    FacesContext context = FacesContext.getCurrentInstance();
                    Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) t).getConstraintViolations();
                    for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                        FacesMessage facesMessage = new FacesMessage(constraintViolation.getMessage());
                        facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
                        context.addMessage(null, facesMessage);
                    }
                }
                t = t.getCause();
            }
        }
    }
}

jsf页面示例:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head></h:head>
    <h:body>
        <h:form>
            <h:messages id="messages" />
            <h:inputText value="#{myController.text}" />
            <h:commandButton value="Save" action="#{myController.saveNewEntity()}" />
        </h:form>
    </h:body>
</html>

MyEntityFacade仅从实体管理器进行持久化调用。

如前所述,应用程序运行良好,正确的消息已显示,但我希望在Glassfish控制台中避免此异常。

这里讨论的将persistence.xml中的验证模式设置为NONE是没有选择的,因为我想要验证。

我在2.2版中使用JSF,实现是Mojarra。Bean验证的版本是1.1,实现是Hibernate Validator。应用服务器是Glassfish 4.0。

共有1个答案

公良信然
2023-03-14

类级约束不适用于JSF。看看这个答案。当您按下“保存”按钮时,JSF只检查名称是否至少有2个字符,并且不考虑有效性约束。另一方面,JPA抱怨bean无效,并抛出异常。

使现代化

1)@size约束位于MyEntity.name属性上,而在faclet中您有MyController.text属性。在JSF透视图中没有什么要验证的。它根本不了解MyEntity。

2)ValidEntity总是无效的,所以JPA总是会抛出异常(除非您禁用验证),即使您在faclet中正确设置了MyEntity.name

 类似资料:
  • 我想验证社会安全号码是否存在于数据库中。这是我的验证器。 在Validator中,我有一个@EJB userDao,我有一个方法此方法: 但是当我执行此方法时,我有一个错误: 警告:StandardWrapperValve[面向Servlet]:PWC1406:Servlet。servlet Faces的service()servlet引发了异常java。pl.ePrzychodnia处的lang

  • 我必须使用jsf配置Spring Security 5,此下面的代码在Spring Security 4中工作正常,但当我迁移到版本5时,身份验证过程不会触发: 登录表单如下所示: JSF Bean: 以及安全配置: 当我提交登录表单时,身份验证未被触发!我在这个配置中忘记了什么吗? 在Spring Security 4中,触发登录和注销的操作如下所示: 和注销: 我尝试将j_spring_sec

  • 我正在使用JSF2(MyFaces2.2.9)和Bean验证(Hibernate Validator5.2.2.final)。 我在一个bean上使用@NotNull注释,它是我的托管bean的一个属性。 (ManagedBean类) (Bean类) 预先感谢您的回答。 注意:我真的希望坚持只由JSR303完成的验证,因为这样我就有了一种处理约束的统一方法。所以没有JSF验证器(我知道它可以做同样

  • 这个问题是这个问题的后续:JPA约束违反vs回滚 我做了一些关于JPA和验证API(JSR-303)组合的测试。 我在JPA规范(第101-102页)中发现了以下内容: 默认情况下,默认Bean验证组(默认组)将在预持久性和预更新生命周期验证事件时进行验证 ... 如果validate方法返回的ConstraintViolation对象集不是空的,则持久性提供程序必须抛出javax。验证。Cons

  • 主要内容:验证器标签JSF有内置的验证器验证其UI组件。验证器标签可以验证可以是自定义对象的字段长度,输入类型。 我们必须在节点中使用URI的以下命名空间来包含验证器标签。 验证器标签 下表在JSF 2.0中有重要的验证器标签: 标签 描述 验证字符串的长度 验证数值范围 验证浮点值的范围 使用给定的正则表达式验证JSF组件。 自定义验证器 创建自定义验证器

  • 我想从我的应用程序中提取DTO以将它们作为jar提供给层应用程序。 但我使用了Bean验证,所以DTO使用自定义约束进行注释。这种自定义注释对验证实现具有依赖性(链接)。 因此,我的DTO模块依赖于注释,而注释依赖于验证器,验证器依赖于DAO,然后是完整的核心应用程序。 有没有办法打破这种依赖循环?提供DTO jar而不依赖(或只提供bean验证API)的良好实践是什么? 谢谢