How to @Inject in a PhaseListener
cdi, jsf, jsf-2, phaselistener
Solution
Before JSF 2.2, `PhaseListener`s are not registered as CDI injection targets. Using `@Inject` (and `@EJB`) has effectively no effect in `PhaseListener`s. You'd need to manually grab the CDI managed beans by programmatically evaluating an EL expression referencing the `@Named`'s (implicit) name, or as last resort via JNDI and `BeanManager` which is quite clumsy.
So, if you can't upgrade to JSF 2.2 (which should be compatible with any JSF 2.0/2.1 and Servlet 3.0 compatible web application), then your best bet is programmatically evaluating an EL expression referencing the `@Named` name. Assuming that you've a
@Named("stuff")
public class MyCDIStuff {}
then this should do:
FacesContext context = event.getFacesContext();
MyCDIStuff stuff = context.getApplication().evaluateExpressionGet(context, "#{stuff}", MyCDIStuff.class);
// ...
Problem
I have added a `PhaseListener` to `faces-config.xml`: ``` <lifecycle> <phase-listener>com.project.NotificationListener</phase-listener> </lifecycle> ``` The class seems to be otherwise correct as it is pretty simple. ``` public class NotificationListener implements PhaseListener { @Inject private MyCDIStuff stuff; @Override public PhaseId getPhaseId() { return PhaseId.RENDER_RESPONSE; } @Override public void beforePhase(PhaseEvent event) { this.stuff.doStuff(); } } ``` The 'beforePhase' method gets called correctly, however the MyCDIStuff object is null. I tried using annotation `@Singleton` for the class which most likely was incorrect, and it didn't make the injection work either. Is there a way to inject CDI managed beans in the `PhaseListener`?