6

我知道使用 @EJB 注释的注入只能在 EJB 类、servlet 或 JSF 托管 bean 中进行,但同时我需要在 POJO 类中拥有一些注入业务接口的实例,所以我想过做以下事情:

在我的 JSF 托管 bean

@EJB BusinessInterfaceLocal businessInterface;

private void someMethod(){
    PojoInterface pojo = new PojoClass(this.businessInterface);
}

在我的 POJO 类中,我有这个构造函数

BusinessInterfaceLocal businessInterface;    

public PojoClass(BusinessInterfaceLocal businessInterface){
   this.businessInterface = businessInterface;

   //The following throws a Null Pointer Exception
   this.businessInterface.someMethodCall();
}

以上不应该正常工作吗?但事实并非如此,PojoClass 中的 businessInterface 对象被评估为 null,从而引发空指针异常。

我希望有人能指出我做错了什么。

提前致谢。

4

3 回答 3

11

确认

是否有可能在注入 EJB 之前创建 PojoClass。我的意思是,你在哪里调用“someMethod”?它在托管bean的构造函数中吗?变量不会丢失其引用值。

您说您可以看到托管 bean 中的 BusinessInterfaceLocalbean 不为空,您能在检查后验证您创建了 Pojo 吗?

替代解决方案:

解决方案 1 您可以将 POJO 用作无状态 bean,我认为这样做没有任何问题,除非您当然尝试在 EE 容器之外使用 POJO,也就是说,看起来并非如此.

使 POJO 无状态将使您能够注入 EJB。

解决方案 2 或 JNDI 查找,实现如下:

@Stateless(name="myEJB")
public class MyEJB {

  public void ejbMethod() {
  // business logic
  }

}

public class TestEJB {

  public static void main() {
  MyEJB ejbRef = (MyEJB) new InitialContext().lookup("java:comp/env/myEJB");
  ejbRef.ejbMethod();
  }
}
于 2012-11-06T11:29:15.463 回答
1

NullPointerException使用上面显示的代码,可以在指示的行处抛出a 的唯一方法是businessInterface托管 bean 中的字段是否为空。当从一个对象传递到另一个对象时,引用不会神秘地变为空,并且PojoClass不会做任何会导致变量变为空的事情。我建议您进行一些调试或日志记录,以确定在调用构造函数时托管 bean 中字段的值。如果它为空,那么问题出在注入到 bean 中,与 POJO 无关,您应该修复它。

如果抛出的异常实际上比您显示的行更深,那么这可能是在错误的上下文中使用 EJB 代理的问题。您可能知道,对 EJB 的引用通常不是对 EJB 本身的引用,而是对某种将方法调用传递给 EJB 的代理。代理存在,因此容器可以介入并执行诸如启动事务、检查授权等操作。代理可能需要调用某些上下文资源来完成其工作,这些资源在从托管 bean 访问 EJB 时可用,但由于某些不明显和扭曲的原因,从 POJO 访问时不可用。这些资源的不可用可能导致NullPointerException. 现在,我认为简单地将托管 bean 的引用传递给 POJO 不太可能让您陷入这种情况;仅当您执行诸如从不同线程访问托管 bean 之类的操作时才会发生这种情况。所以,应该不是这个!

于 2012-11-06T12:15:07.790 回答
0

The problem was caused by me trying to use the businessInterface object in the constructor, while the container injects the ejb only after it's done instantiating the managed bean,

reference to a similar question https://stackoverflow.com/a/6537228/1249304

What I did is that I created a method and annotated it with the @PostConstruct annotation, this way after the container is done with instantiating the managed bean, the annotated method gets called and the businessInterface object is no longer null

@PostContsruct
public void onInit(){
   //businessInterface is no longer null
   businessInterface.someMethod();
}
于 2012-11-11T09:37:10.913 回答