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:
- Windows 7 64 bits
- JDK 1.6.0_31 64 bits
- Eclipse Indigo SR1 64 bits
- Glassfish 3.1.2.2
- EclipseLink 2.3.2 (bundle with GF)
- Weld 1.1.10-Final
- Hibernate Valiation 4.3.0.Final
- Seam Solder 3.1.1.Final
- 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.