How to inject in @FacesValidator with @EJB, @Persi

2019-01-01 11:57发布

问题:

How can I inject a dependency like @EJB, @PersistenceContext, @Inject, @AutoWired, etc in a @FacesValidator? In my specific case I need to inject a Spring managed bean via @AutoWired:

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

    @Autowired
    private UserDao userDao;

    // ...
}

However, it didn\'t get injected and it remains null, resulting in java.lang.NullPointerException. It seems that @EJB, @PersistenceContext and @Inject also doesn\'t work.

How do I inject a service dependency in my validator so that I can access the DB?

回答1:

The @FacesValidator isn\'t managed by the injection container. You need to make it a managed bean. Use Spring\'s @Component, CDI\'s @Named or JSF\'s @ManagedBean instead of @FacesValidator in order to make it a managed bean and thus eligible for dependency injection.

E.g., assuming that you want to use JSF\'s @ManagedBean:

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

You also need to reference it as a managed bean by #{name} in EL instead of as a validator ID in hardcoded string. Thus, so

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

or

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

instead of

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

or

<f:validator validatorId=\"emailExistValidator\" />

This is indeed awkward. The JSF guys have confirmed this embarrassing oversight and they will make the @FacesValidator (and @FacesConverter) an eligible injection target in upcoming JSF 2.2 2.3, see also JSF spec issue 763. For EJBs there\'s a workaround by manually grabbing it from JNDI, see also Getting an @EJB in @FacesConverter and @FacesValidator. If you happen to use the CDI extension MyFaces CODI, then you can also solve it by putting @Advanced annotation on the class.

See also:

  • CDI Injection into a FacesConverter
  • What\'s new in JSF 2.2 - Injection

Update: if you happen to use JSF utility library OmniFaces, since version 1.6 is adds transparent support for using @Inject and @EJB in a @FacesValidator class without any additional configuration or annotations. See also the CDI @FacesValidator showcase example.