在Java类中注入EJB时出现NullPointerException

tim*_*nYE 15 java jsf ejb

我认为这个问题引发了,因为我没有得到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; 
    }
}
Run Code Online (Sandbox Code Playgroud)

执行时,我在"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 ; 
                }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

是不是可以在普通的Java类中注入EJB?我必须做什么,我不必在演示模型中定义DataModel?

谢谢

Bal*_*usC 18

EJB仅在托管bean中注入.当bean由一些注入容器管理时,例如通过JSF自己的@ManagedBean,CDI @Named等,管理bean .您甚至可以在另一个EJB中注入EJB.您不能在非托管类中注入EJB(但是您可以手动从JNDI中获取它,但这很简单).

你基本上有以下选择:

  1. 在@PostConstruct托管bean中,构造数据模型,然后将结果作为参数传递(请注意,这也是标准数据模型的ListDataModel工作方式).

    @PostConstruct
    public void init() {
        lazyUsers = new LazyUserDataModel(service.findAllUsers());
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. make LazyUserDataModelabstract,您要求用户提供结果.

    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();
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这样匿名班的伤害就会减少

    lazyUsers = new LazyUserDataModel() {
        @Override
        public List<User> findAllUsers() {
            return service.findAllUsers();
        }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建LazyUserDataModel一个托管bean,然后注入它.

    @Named @RequestScoped
    public class LazyUserDataModel extends LazyDataModel<User> {
        // ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    同

    @Inject
    private LazyUserDataModel lazyUsers;
    
    Run Code Online (Sandbox Code Playgroud)
  4. 像你想象的那样创建一个完整的匿名实例.


与具体问题无关,没有必要LazyDataModel提供所有记录.它的意图是,它为您提供的可能性,要求只有一个子集,或使用SQL权力记录(LIMIT,OFFSET基于当前分页状态和朋友),这样你就不需要有上百个,如果在Java的内存而不是成千上万的记录,但只有十或者.换句话说,如果你从不使用first和/或pageSize论证load()方法,你很可能完全错误地接近它.

  • 对不起我错了.您在匿名方法中引用它,当然在构造时不会调用它.但至少,这不是好的编码风格.将postconstruct逻辑放在`@ PostConstruct`方法中.保持构造函数为空.最好,您的托管/企业bean不应该有任何显式构造函数. (3认同)

JB *_*zet 5

您只能将 Bean 和 EJB 注入容器创建的 Bean 和 EJB 内。不在您自己实例化的对象内部new。容器不知道您实例化的对象,因此无法在这些对象中注入任何内容。

因此,只需让容器实例化并注入 LazyUserDataModel 对象即可:

@Named
@SessionScoped
public class UserPM {
    @Inject
    private LazyUserDataModel lazyUsers;

    ...
}
Run Code Online (Sandbox Code Playgroud)