私の以前の質問、JSR 303 Bean 検証、拡張された ConstraintValidator は CDI を使用できません、Seam 検証モジュールは、コードを繰り返さずにすべての 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)
Constraint Validator で CDI を JPA と一緒に使用できるかどうかはわかりません。さらにアドバイスをお願いできますか?よろしくお願いいたします。ご連絡をお待ちしております。
私の環境は次のとおりです。
- Windows 7 64 ビット
- JDK 1.6.0_31 64 ビット
- Eclipse インディゴ SR1 64 ビット
- グラスフィッシュ 3.1.2.2
- EclipseLink 2.3.2 (GF にバンドル)
- 溶接 1.1.10-最終
- Hibernate Valiation 4.3.0.Final
- シームはんだ 3.1.1.Final
- Seam Validation 3.1.0.Final
私のコーディング例
ユーティリティ
@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 検証を無効にしています。