Как интегрировать проверку JPA с проверкой CDI и шва

Что касается моего предыдущего вопроса, проверки бина JSR 303, расширенный ConstraintValidator не может использовать CDI, модуль проверки шва дает мне идеальное решение для централизации всей бизнес-проверки 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 с Constraint Validator вместе с 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. Шовный припой 3.1.1. Финал
  9. Подтверждение шва 3.1.0. Финал

Мой пример кодирования

Утилита

@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());
    }
}

Бин данных как бин сущности

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

Фасоль JSF

@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 ответ

Я столкнулся с этой же проблемой и исправил ее, добавив:

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

в свойствах моего модуля персистентности в файле persistence.xml. Как только вы это сделаете, вы можете удалить режим проверки.

Другие вопросы по тегам