如何将JPA验证与CDI和Seam验证集成

时间:2012-10-15 11:10:27

标签: jpa-2.0 cdi bean-validation seam3

关于我之前的问题,The JSR 303 bean validation, The extended ConstraintValidator cannot use the CDISeam Validation Module为我提供了一个完美的解决方案,可以集中所有JSF和EJB业务验证,而无需重复代码。

无论如何,当我尝试让 JPA(EclipseLink)执行验证时,系统会给我以下内容:

  

java.lang.IllegalStateException:WEB9031:WebappClassLoader无法加载资源[javax.enterprise.inject.spi.BeanManager], ,因为它尚未启动,或者已经停止

完整堆栈跟踪如下: -

Caused by: java.lang.IllegalStateException: WEB9031: WebappClassLoader unable to load resource [javax.enterprise.inject.spi.BeanManager], because it has not yet been started, or was already stopped
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1401)
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1359)
at org.jboss.seam.validation.InjectingConstraintValidatorFactory.getInstance(InjectingConstraintValidatorFactory.java:67)
at org.hibernate.validator.internal.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:346)
at org.hibernate.validator.internal.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:334)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:155)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:125)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:86)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:442)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:387)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:351)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:303)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:133)
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:84)
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.prePersist(BeanValidationListener.java:62)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:698)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyEJB30Listeners(DescriptorEventManager.java:641)
at org.eclipse.persistence.descriptors.DescriptorEventManager.executeEvent(DescriptorEventManager.java:200)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectClone(UnitOfWorkImpl.java:4257)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4234)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:513)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4176)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:440)

我不确定我是否可以将带有约束验证器的CDI与JPA一起使用。你能帮忙进一步建议吗?非常感谢您的帮助。我很期待很快收到你的来信。

我的环境如下:

  1. Windows 7 64位
  2. JDK 1.6.0_31 64位
  3. Eclipse Indigo SR1 64位
  4. Glassfish 3.1.2.2
  5. EclipseLink 2.3.2(与GF捆绑)
  6. Weld 1.1.10-Final
  7. Hibernate Valiation 4.3.0.Final
  8. Seam Solder 3.1.1.Final
  9. Seam Validation 3.1.0.Final
  10. 我的示例编码

    实用程序

    @Singleton
    public class MyUtility {
        public boolean isValid(final String input) {
           return (input != null) || (!input.trim().equals(""));
        }
    }
    

    约束注释

    @Retention(RetentionPolicy.RUNTIME)
    @Target({
        ElementType.TYPE,
        ElementType.ANNOTATION_TYPE,
        ElementType.FIELD
        })
    @Constraint(validatedBy = Validator.class)
    @Documented
    public @interface Validatable {
        String  message() default "Validation is failure";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    约束验证器

    public class Validator extends ConstraintValidator<Validatable, MyBean> {
        //
        //----> Try to inject the utility with Seam validation
        //
        @Inject
        private MyUtility myUtil;
    
        public void initialize(ValidatableconstraintAnnotation) {
            //nothing
        }
    
        public boolean isValid(final MyBean myBean, 
                               final ConstraintValidatorContext constraintContext) {
    
            if (myBean == null) {
                return true;
            }
            //
            //----> It works as expected, but not for the JPA layer
            //
            return this.myUtil.isValid(myBean.getName());
        }
    }
    

    数据bean作为实体bean

    @Entity
    //--other JPA annotation
    @Validatable
    public class MyBean {
        private String name;
        //Getter and Setter here
    }
    

    JSF支持bean

    @Named
    @SessionScoped
    public class Page1 {
        //javax.validation.Validator
        @Inject
        private Validator validator;
    
        @Inject
        private MyBean myBean;
    
        @PersistenceContext(unitName = "mydb-pu")
        private EntityManager em;
    
        //Submit method
        public void submit() {
            Set<ConstraintViolation<Object>> violations = 
                             this.validator.validate(this.myBean);
            if (violations.size() > 0) {
                //Handle error here.
            }
            this.em.persist(this.myBean);
        }
    }
    

    Persistence.xml

    <persistence-unit name="mydb-pu"
        transaction-type="JTA">
        <jta-data-source>jdbc/mydb</jta-data-source>
        <class>...</class>
    
        <!-- If I comment this, the exception occurs -->
        <validation-mode>NONE</validation-mode>
    
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
            <property name="eclipselink.ddl-generation" value="none" />
            <property name="eclipselink.ddl-generation.output-mode" value="both"/>
        </properties>
    
    </persistence-unit>
    

    Validation.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <validation-config
       xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration
    validation-configuration-1.0.xsd">
    
        <constraint-validator-factory>
            org.jboss.seam.validation.InjectingConstraintValidatorFactory
        </constraint-validator-factory>
    </validation-config>
    

    关于提到的Persistence.xml,如果我删除验证模式,系统会给我一个例外。目前,我禁用JPA验证作为临时解决方案。

1 个答案:

答案 0 :(得分:2)

我遇到了同样的问题并通过添加:

修复了它
<property name="javax.persistence.validation.factory" value="org.jboss.seam.validation.InjectingConstraintValidatorFactory"/>

到persistence.xml中的持久性单元属性。完成后,您可以删除验证模式。