如何在PhaseListener中@Inject

时间:2013-11-12 13:16:20

标签: jsf jsf-2 cdi phaselistener

我已将PhaseListener添加到faces-config.xml

<lifecycle>
    <phase-listener>com.project.NotificationListener</phase-listener>
</lifecycle>

这个课似乎是正确的,因为它非常简单。

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();
    }
}

正确调用'beforePhase'方法,但MyCDIStuff对象为null。我尝试使用注释@Singleton作为最可能不正确的类,并且它也没有使注入工作。

有没有办法在PhaseListener中注入CDI托管bean?

2 个答案:

答案 0 :(得分:13)

在JSF 2.2之前,PhaseListener未注册为CDI注入目标。使用@Inject(和@EJB)在PhaseListener中实际上没有效果。您需要通过以编程方式评估引用@Named(隐式)名称的EL表达式来手动获取CDI托管bean,或者通过JNDI和BeanManager作为最后的手段,这非常笨拙。

因此,如果您无法升级到JSF 2.2(应该与任何JSF 2.0 / 2.1和Servlet 3.0兼容的Web应用程序兼容),那么您最好的选择是以编程方式评估引用@Named的EL表达式名称。假设你有一个

@Named("stuff")
public class MyCDIStuff {}

然后这应该做:

FacesContext context = event.getFacesContext();
MyCDIStuff stuff = context.getApplication().evaluateExpressionGet(context, "#{stuff}", MyCDIStuff.class);
// ...

答案 1 :(得分:4)

如果你不能去JSF 2.2,你最好的选择是使用Deltaspike Core。

它提供 MyCDIStuff myCDIStuff = BeanProvider.getContextualReference(MyCDIStuff.class, false);

Deltaspike是你应该如何得到的东西,而不是自己发明。例如,如果您必须拥有BeanManager(例如触发事件),那么Deltaspike核心也会提供BeanManagerProvider

http://deltaspike.apache.org/core.html