How to integrate JPA validation with CDI and Seam Validation
Asked Answered
H

1

6

Regarding to my previous question, The JSR 303 bean validation, The extended ConstraintValidator cannot use the CDI, The Seam Validation Module give me a perfect solution for centralizing all JSF and EJB business validation with out repeating the code.

Anyhow when I try to let the JPA (EclipseLink) to perform the validation, the system give me as the following:

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

The full stack trace is as the following:-

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)

I'm not sure if I can use the CDI with Constraint Validator together with JPA or not. Could you please help to advice further? Thank you very much for your help in advance. I'm looking forward to hearing from you soon.

My Environment is as follows:

  1. Windows 7 64 bits
  2. JDK 1.6.0_31 64 bits
  3. Eclipse Indigo SR1 64 bits
  4. Glassfish 3.1.2.2
  5. EclipseLink 2.3.2 (bundle with 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

My example coding

The utility

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

The constraint annotation

@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 {};
}

The constraint validator

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

The data bean as an Entity bean

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

The JSF backing 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);
    }
}

The 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>

The 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>

Regarding to the mentioned Persistence.xml, if I remove the validation-mode, the system gives me an exception. At the moment, I disable the JPA validation as an interim solution.

Hardtack answered 15/10, 2012 at 11:10 Comment(3)
Can you describe in more detail your configuration? Some actual code would be good as well.Infighting
Like Hardy said, some more code, app server and version would both be helpful.Lerma
Hi Hardy and LightGuard, I've edited my question and provided further information as your request.Hardtack
M
2

I came across this same issue and fixed it by adding:

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

to my persistence unit properties in the persistence.xml. Once you do that you can remove the validation-mode.

Madeleinemadelena answered 15/8, 2013 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.