试图访问托管bean构造函数中的@EJB bean时出现NullPointerException



我有一个EJB服务。

@Stateless
public class SomeService {}

我想把它注入到一个viewscoped bean中,并用它初始化:

@ManagedBean
@ViewScoped
public class ViewBean implements Serializable {
    @EJB
    private SomeService someService;
    public ViewBean() {
        System.out.println(someService.getEntity());
    }
}

但是,它抛出以下异常:

com.sun.faces.mgbean.ManagedBeanCreationException: Cant instantiate class: com.example.ViewBean.
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:193)
    at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:102)
    at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409)
    at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269)
    at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
    at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    [snip]
Caused by: java.lang.NullPointerException
    at com.example.ViewBean.<init>(ViewBean.java:42)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at java.lang.Class.newInstance0(Class.java:374)
    at java.lang.Class.newInstance(Class.java:327)
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:188)
    ... 62 more

这是如何引起的,我该如何解决?

换句话说,您期望EJB注入在下面工作:

ViewBean viewBean;
viewBean.someService = new SomeService(); // EJB injected, so that constructor can access it.
viewBean = new ViewBean(); // ViewBean constructed.

然而,这在技术上是不可能的。当实例根本没有被构造时,是不可能赋值实例变量的。

在构造后直接基于注入的依赖项执行任务的规范方法是使用@PostConstruct注释方法。

因此,要解决具体问题,只需替换

public ViewBean() {

@PostConstruct
public void init() { // Note: Method name is fully free to your choice.

这种方式下的过程大致如下:

ViewBean viewBean;
viewBean = new ViewBean(); // ShiftBean constructed.
viewBean.someService = new SomeService(); // EJB injected.
viewBean.init(); // PostConstruct invoked.

请注意,具体问题与视图范围完全无关。在使用请求、会话或应用程序作用域bean时,您会遇到完全相同的问题。因此,这是另一个证据,表明您从未通过使用不同的作用域进行测试来实际排除它作为原因。

最新更新