在 Java 类中注入 EJB 时出现 NullPointerException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18017008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NullPointerException when injecting EJB in Java Class
提问by timmornYE
I think this problem raises because I didn't get something with EJBs. I have a service class for my entity, which is @Stateless. When I use it by injecting with @EJB in my session scoped presentation model, all is ok. But now I wanted to use this EJB service in a DataModel I have overwritten for use in my presentation model:
我认为这个问题的出现是因为我没有得到 EJB 的帮助。我的实体有一个服务类,它是@Stateless。当我通过在会话范围表示模型中注入 @EJB 来使用它时,一切正常。但是现在我想在我已经覆盖以在我的表示模型中使用的 DataModel 中使用这个 EJB 服务:
public class LazyUserDataModel extends LazyDataModel<User> {
@EJB
private UserService service;
@Override
public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) {
List<User> users;
users= service.findAllUsers();
this.setRowCount(users.size());
return users;
}
}
On execution I get a NullPointerException at position "users= service.findAllUsers();" The same works, when I overwrite this DataModel in my presentation model:
在执行时,我在“users= service.findAllUsers();”位置得到一个 NullPointerException 当我在演示模型中覆盖此 DataModel 时,同样有效:
@Named
@SessionScoped
public class UserPM {
@EJB
private UserService service;
private LazyDataModel<User> lazyUsers;
public UserPM() {
// Don't works
//lazyUsers = new LazyUserDataModel();
lazyUsers = new LazyDataModel() {
@Override
public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) {
List<User> users;
users = service.findAllUsers();
this.setRowCount(users .size());
return users ;
}
};
}
}
Isn't it possible to Inject an EJB in a normal Java Class? What must I do that I don't have to define the DataModel in the presentation model?
不能在普通的 Java 类中注入 EJB 吗?我必须做什么才能不必在表示模型中定义 DataModel?
Thanks
谢谢
采纳答案by BalusC
EJBs are only injected in managed beans. A bean is managed when it's managed by some injection container, such as via JSF's own @ManagedBean
, CDI's @Named
, etc. You can even inject an EJB in another EJB. You cannot inject an EJB in an unmanaged class (you can however manually grab it from JNDI, but that's plain ugly).
EJB 仅注入托管 bean。当一个 bean 被某个注入容器管理时,它就会被管理,例如通过 JSF 自己的@ManagedBean
、CDI 的@Named
等等。您甚至可以在另一个 EJB 中注入一个 EJB。您不能在非托管类中注入 EJB(但是您可以从 JNDI 手动获取它,但这很丑陋)。
You've basically the following options:
您基本上有以下选项:
In
@PostConstruct
of your managed bean, construct the datamodel whereby you pass the result as argument (note that this is also how standard data models likeListDataModel
work).@PostConstruct public void init() { lazyUsers = new LazyUserDataModel(service.findAllUsers()); }
Make
LazyUserDataModel
abstract whereby you ask the user to provide the result.public abstract class LazyUserDataModel extends LazyDataModel<User> { @Override public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) { List<User> users; users = findAllUsers(); this.setRowCount(users.size()); return users ; } public abstract List<User> findAllUsers(); }
so that the anonymous class hurts less
lazyUsers = new LazyUserDataModel() { @Override public List<User> findAllUsers() { return service.findAllUsers(); } };
Make
LazyUserDataModel
a managed bean as well and inject it instead.@Named @RequestScoped public class LazyUserDataModel extends LazyDataModel<User> { // ... }
with
@Inject private LazyUserDataModel lazyUsers;
Create a fullfledged anonymous instance like as you figured.
在
@PostConstruct
您的托管 bean 中,构建数据模型,通过该模型将结果作为参数传递(请注意,这也是标准数据模型的ListDataModel
工作方式)。@PostConstruct public void init() { lazyUsers = new LazyUserDataModel(service.findAllUsers()); }
让
LazyUserDataModel
抽象的,让你要求用户提供结果。public abstract class LazyUserDataModel extends LazyDataModel<User> { @Override public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) { List<User> users; users = findAllUsers(); this.setRowCount(users.size()); return users ; } public abstract List<User> findAllUsers(); }
这样匿名类的伤害就会减少
lazyUsers = new LazyUserDataModel() { @Override public List<User> findAllUsers() { return service.findAllUsers(); } };
也制作
LazyUserDataModel
一个托管 bean 并注入它。@Named @RequestScoped public class LazyUserDataModel extends LazyDataModel<User> { // ... }
和
@Inject private LazyUserDataModel lazyUsers;
像您想象的那样创建一个成熟的匿名实例。
Unrelatedto the concrete problem, there's no point of having a LazyDataModel
whereby you provide allrecords. Its intent is that it offers you the possibility to request only a subset or records using SQL powers (LIMIT
, OFFSET
and friends) based on the current paginated state so that you don't need to have hundreds if not thousands records in Java's memory but only ten or so. In other words, if you are never using first
and/or pageSize
argument of the load()
method, you're most likely approaching it completely wrong.
与具体问题无关,没有必要LazyDataModel
提供所有记录。它的目的是让您可以根据当前的分页状态使用 SQL 功能(和朋友)仅请求一个子集或记录LIMIT
,OFFSET
这样您就不需要在 Java 内存中拥有数百甚至数千条记录,而只需要 10 个记录或者。换句话说,如果你从不使用first
和/或pageSize
参数的load()
方法,你很可能完全错误地接近它。
回答by JB Nizet
You can only inject beans and EJBs inside beans and EJBs that are created by the container. Not inside objects that you instantiate yourself using new
. The container is unaware of the objects that you instantiate, and thus is unable to inject anything in these objects.
您只能在容器创建的 bean 和 EJB 中注入 bean 和 EJB。不在您使用实例化自己的对象内部new
。容器不知道您实例化的对象,因此无法在这些对象中注入任何内容。
So, simply let the container instantiate and inject the LazyUserDataModel object:
因此,只需让容器实例化并注入 LazyUserDataModel 对象:
@Named
@SessionScoped
public class UserPM {
@Inject
private LazyUserDataModel lazyUsers;
...
}