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?
If you're already on JSF 2.3 or newer, and want to inject CDI-supported artifacts via e.g. @EJB
, @PersistenceContext
or @Inject
, then simply add managed=true
to the @FacesValidator
annotation to make it CDI-managed.
@FacesValidator(value="emailExistValidator", managed=true)
If you're not on JSF 2.3 or newer yet, then you basically 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 CDI's @Named
:
@Named
@ApplicationScoped
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}" />
instead of
<h:inputText ... validator="emailExistValidator" />
or
<f:validator binding="#{emailExistValidator}" />
instead of
<f:validator validatorId="emailExistValidator" />
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 JSF utility library OmniFaces, since version 1.6 it 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.