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?
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.