我是cdi的新手,这是我的第一步。 我在ejb模块中有一个bean:
@Stateless
public class TestBean {
public String getIt(){
return "test";
}
}
我在战争模块中有一个POJO(我试过@EJB和@Inject - 相同的结果)
public class SaveAction extends Action{
@EJB
private TestBean bean;
@Override
public void execute(){
....
String test = bean.getIt(); //HERE I GET java.lang.NullPointerException
...
}
}
战争和ejb都在耳内。在日志中我看到
EJB5181:EJB TestBean的可移植JNDI名称: 【JAVA:全球/ example.com /我的EJB / testBean就com.example.TestBean, 的java:全球/ example.com /我的EJB / testBean这个]]]
由此我得出结论bean被初始化 - 但我找不到它。我做错了什么?
答案 0 :(得分:3)
CDI和其他依赖注入容器不使用魔法!它只是普通的java代码,它不能比任何其他任何地方编写的java代码做得更多或更少。因此,当通过new
直接实例化对象时,框架不可能进行注入:
SaveAction action = new SaveAction();
// don't expect any injection has happened - it can't! no magic!
// action.bean is still null here!
框架不知道像SaveAction这样的对象已被实例化。 (因此有必要以某种方式告知框架有关新创建的对象 - 但是构造函数和'new'语句都没有这样做!只想一下如何编写这样的框架代码!这是不可能的!*)
要使注入工作,必须由容器创建对象!否则它不受管理! (另见Web Beans specification (JSR 299)的第3.7章)。
执行此操作的最佳方法是让容器将对象注入另一个已管理的bean。这似乎只是解决了这个问题,但是你的应用程序中有一些已经托管的bean,比如servlet!
建议:让您的SaveAction CDI识别(例如用@Default
注释)并将其注入您的servlet!
教程:
*)从理论上讲,应该可以使用面向方面的编程或检测来操作bean的构造函数,以便在调用它们时通知容器。但这是一个非常复杂的概念,我认为有许多未解决的问题。