2013-11-12 2 views
9

Согласно вики Glassfish 4.0, Glassfish 4.0 должен включать JSR349 Bean Validation 1.1 .: GF4 wiki linkBean-Validation 1.1 в Glassfish 4.0 - CDI Injection не работает по назначению

Согласно спецификации JSR349, CDI Инъекции должны работать из коробки: Bean Validation 1.1. CDI Integration

Так что я изменил мою pom.xml соответственно:

<dependency> 
     <groupId>javax.validation</groupId> 
     <artifactId>validation-api</artifactId> 
     <version>1.1.0.Final</version> 
     <scope>provided</scope> 
</dependency> 

И попытался нагнетание CDI Bean в ConstraintValidator:

public class UniqueEmaiValidator implements ConstraintValidator<UniqueEmail, String> { 

    @Inject 
    private UserAccountService accountService; 

    @Override 
    public void initialize(UniqueEmail constraintAnnotation) { 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     return !accountService.userExistsByEmail(value); 
    } 
} 

Однако при тестировании приложения (Running Arquillian 1.1.1. с arquillian-glassfish-remote-3.1 1.0.0.CR4), валидация всегда будет терпеть неудачу, потому что userAccountService имеет значение NULL и, таким образом, в конечном итоге выбросит NullPointerException.

Что мне недостает, чтобы убедиться, что функция проверки фасов 1.1 работает?

редактировать:

A) может подтвердить это не вызвано Arquillian удаленного тестирования - также бросить NPEx. при запуске на сервере

B) Запуск на GlassFish Server, Open Source Edition 4.0 (сборка 89)

C) Я снова построил боб-validation.jar явно с помощью 5.0.1.FINAL из спящего режима Validator. mvn package выход:

[INFO] Building Validation API (JSR 349) version 1.1.0.Final, Hibernate Validator version 5.0.1.Final and its dependencies repackaged as OSGi bundle 2.1.92

При запуске сервера GlassFish я получаю встречено со следующим:

INFO: GlassFish Server Open Source Edition 4.0 (89) startup time : Felix (5,736ms), startup services(2,078ms), total(7,814ms) 
INFO: HV000001: Hibernate Validator 5.0.1.Final 

Так что я полагаю, что восстановление сделал работу. Однако, это не решить мою проблему в NullPointerException:/

D) @Gunnar

Это класс объектов с помощью @Constraint аннотацию:

@Entity 
public class UserAccount extends AbstractEntity implements VisibilitySettings { 

    @UniqueEmail 
    private String email; 
    [...] 
} 

Сама Аннотация:

@Constraint(validatedBy = {UniqueEmailValidator.class}) 
@Target(ElementType.FIELD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface UniqueEmail { 

    String message() default "{validator.security.useraccount.emailexists}"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 
} 

И соответствующие ConstraintValidator:

public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> { 

    @Inject 
    private UserAccountService accountService; 

    @Override 
    public void initialize(UniqueEmail constraintAnnotation) { 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     return !accountService.userExistsByEmail(value); 
    } 
} 

UserAccountService помечается @ApplicationScoped @Transactional

+0

Это должно работать, и есть даже тесты TCK для обеспечения того, что инъекция CDI работает в экземплярах ConstraintValidator. Есть ли что-то еще в журналах, кроме исключения NullPointerException? Включает ли инъекция CDI вне проверки Bean? Восстановление артефактов Glassfish не требуется. Он должен работать из коробки, а Hibernate Validator 5.0.1.Final - это правильная версия. – Hardy

+2

Как вы получаете свой 'Validator', введя его через' @ Inject'? Обратите внимание, что интеграция CDI не будет работать из коробки при ручной загрузке валидатора с помощью 'Validation.buildDefaultValidatorFactory()'. – Gunnar

+1

5.0.0.Финал отлично подходит. 5.0.1.Final - это всего лишь незначительный выпуск технического обслуживания. – Hardy

ответ

3

интеграции CDI не будет работать из коробки, когда вручную развернув валидатор через Validation.buildDefaultValidatorFactory().

При выполнении проверки как части жизненного цикла объекта через JPA интеграция CDI должна работать; Если этого не произойдет, все равно может возникнуть проблема с тем, как Bean Validation интегрируется в GlassFish.Если это действительно так, вы можете обойти проблему, настроив фабрику валидатора настраиваемых ограничений в META-INF/validation.xml, которая создает управляемые экземпляры проверки CDI.

Для этого вы можете использовать the factory, предоставленный интеграцией CDI Hibernate Validator, в качестве отправной точки. Обратите внимание, что фабрике нужен конструктор по умолчанию, хотя при настройке через XML; для удовлетворения этого требования вы можете получить ссылку на BeanManager через JNDI.

+0

Благодарим вас за ответ. Я исследовал, почему мы изменили с '' @Inject Validator v'' на Factory - получается тот парень, который сделал это, чтобы установить '' MessageInterpolator'' в '' Validator'' для i18n. Как это будет работать при инъекции через CDI? – chzbrgla

+0

Хорошо. Получил это - легко. Напишите мою собственную реализацию '' MessageInterpolator'' и поместите ее в '' WEB-INF/validation.xml''. – chzbrgla

+0

@Gunhar Я вижу, что вы один из авторов «InjectingConstraintValidatorFactory». У меня возникли проблемы с получением или проверкой компонентов в целом, работая с RESTEasy в встроенном Jetty. Не могли бы вы взглянуть на мой вопрос [здесь] (http://stackoverflow.com/questions/21694596/resteasy-cdi-embedded-jetty-bean-validation-is-ignored)? –

3

Я решил. Я создал Qualifier аннотацию:

@Qualifier 
@Retention(RUNTIME) 
@Target({TYPE,FIELD}) 
public @interface Validation { 

} 

Я аннотированный мой ConstraintValidator:

@Validation 
public class MyValidatorImpl implements ConstraintValidator<MyValidator, MyBean> { 

} 

Я создал ConstraintValidatorFactory:

public class CDIConstraintValidatorFactory implements ConstraintValidatorFactory { 

    @Override 
    public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> type) { 
     try{ 

      T t = getBeanInstance(type); 
      if(t==null){ 
       t = type.newInstance(); 
      } 
      return t; 
     }catch(Exception e){ 
      throw new RuntimeException(e); 
     } 
    } 

    private BeanManager getBeanManager() throws NamingException { 
      String name = "java:comp/" + BeanManager.class.getSimpleName(); 
      InitialContext ic = new InitialContext(); 
      BeanManager beanManager = (BeanManager) ic.lookup(name); 
      return beanManager; 
    } 

    public <T> T getBeanInstance(final Class<T> type) throws Exception{ 
     BeanManager beanManager = getBeanManager(); 
     Validation v = type.getAnnotation(Validation.class); 
     if(v!=null){ 
      final Set<Bean<?>> beans = beanManager.getBeans(type,v); 
      beanManager.resolve(beans); 
      if(!beans.isEmpty()){ 
       final Bean<T> bean = (Bean<T>) beanManager.resolve(beans); 
       final CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean); 
       return (T) beanManager.getReference(bean, type,creationalContext); 
      }else{ 
       return null; 
      } 
     }else{ 
      return null; 
     } 
    } 



} 

, а затем я registried это мой 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.1.xsd"> 
     <constraint-validator-factory>xxx.be.framework.validator.CDIConstraintValidatorFactory</constraint-validator-factory> 
</validation-config> 

приветствует, Giancarlo

+0

Он работает для моей реализации CustomConstraintValidator с Injection, но я получил новую ошибку от других случайных ограничений без Inject-ed filed 'java.lang.RuntimeException: javax.naming.NameNotFoundException: java: comp/BeanManager' –

+0

этот пример работает с jboss. какие серверы приложений вы используете? –

Смежные вопросы