Как вставить в @FacesValidator с помощью @EJB, @PersistenceContext, @Inject, @Autowired

Как я могу вложить зависимость, например @EJB, @PersistenceContext, @Inject, @AutoWired и т.д. в @FacesValidator? В моем конкретном случае мне нужно ввести Spring управляемый bean через @AutoWired:

@FacesValidator("emailExistValidator")
public class EmailExistValidator implements Validator {

    @Autowired
    private UserDao userDao;

    // ...
}

Однако он не вводился и оставался null, в результате получилось java.lang.NullPointerException. Похоже, что @EJB, @PersistenceContext и @Inject также не работают.

Как мне добавить зависимость службы в моем валидаторе, чтобы я мог получить доступ к БД?

Ответ 1

@FacesValidator не управляется контейнером для инъекций. Вам нужно сделать его управляемым bean. Используйте Spring @Component, CDI @Named или JSF @ManagedBean вместо @FacesValidator, чтобы сделать его управляемым bean и, следовательно, иметь право на инъекцию зависимостей.

Например, если вы хотите использовать JSF @ManagedBean:

@ManagedBean
@RequestScoped
public class EmailExistValidator implements Validator {
    // ...
}

Вам также нужно ссылаться на него как на управляемый bean на #{name} в EL, а не как идентификатор проверки подлинника в hardcoded string. Таким образом,

<h:inputText ... validator="#{emailExistValidator.validate}" />

или

<f:validator binding="#{emailExistValidator}" />

вместо

<h:inputText ... validator="emailExistValidator" />

или

<f:validator validatorId="emailExistValidator" />

Это действительно неудобно. Ребята из JSF подтвердили этот смущающий надзор, и они сделают @FacesValidator@FacesConverter) подходящую цель инъекции в предстоящем JSF 2.2 2.3, см. Также Спецификация спецификации JSF 763. Для EJB существует временное решение, вручную беря его из JNDI, см. Также Получение @EJB в @FacesConverter и @FacesValidator. Если вам придётся использовать расширение CDI MyFaces CODI, вы также можете решить его, добавив аннотацию @Advanced к классу.

См. также:


Обновить: если вы используете служебную библиотеку JSF OmniFaces, поскольку версия 1.6 добавляет прозрачность поддержка использования @Inject и @EJB в классе @FacesValidator без каких-либо дополнительных настроек или аннотаций. См. Также пример демонстрации CDI @FacesValidator.