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:
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.
Data validation is a common task that occurs in all layers of an application, including persistence. The Java™ Persistence API (JPA) 2.0 provides support for the Bean Validation API so that data validation can be done at run time.
Hibernate Validator allows to express and validate application constraints. The default metadata source are annotations, with the ability to override and extend through the use of XML. It is not tied to a specific application tier or programming model and is available for both server and client application programming.
Validation is the process of verifying that some data obeys one or more pre-defined constraints. It is, of course, a very common use case in most applications. The Java Bean Validation framework (JSR-380) has become the de-facto standard for handling this kind of operations in Java.
In the setUp() method, a Validator instance is retrieved from the ValidatorFactory . Validator instances are thread-safe and may be reused multiple times.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With