NullPointerException when injecting EJB in Java Class

2022-09-03 13:32:31

我认为这个问题之所以出现,是因为我没有从EJB中获得一些东西。我的实体有一个服务类,这是@Stateless。当我在会话范围的演示模型中注入@EJB来使用它时,一切都很好。但是现在我想在数据模型中使用此 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; 
    }
}

在执行时,我在位置“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 ; 
                }
        };
    }
}

难道不可能在普通的Java类中注入EJB吗?我必须做些什么,而不必在表示模型中定义 DataModel?

谢谢


答案 1

EJB 仅注入受管豆中。当一个豆子由一些注入容器管理时,例如通过JSF自己的,CDI等进行管理。您甚至可以在另一个 EJB 中注入一个 EJB。你不能在非托管类中注入 EJB(但是你可以从 JNDI 手动获取它,但这太难看了)。@ManagedBean@Named

您基本上具有以下选项:

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

    @PostConstruct
    public void init() {
        lazyUsers = new LazyUserDataModel(service.findAllUsers());
    }
    

  2. 进行抽象,从而要求用户提供结果。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();
        }
    };
    

  3. 也制作一个受管豆,然后注入它。LazyUserDataModel

    @Named @RequestScoped
    public class LazyUserDataModel extends LazyDataModel<User> {
        // ...
    }
    

    @Inject
    private LazyUserDataModel lazyUsers;
    

  4. 创建一个完整的匿名实例,就像您想象的那样。


具体问题无关,没有必要提供所有记录。它的目的是为您提供基于当前分页状态的SQL电源(和朋友)仅请求子集或记录的可能性,这样您就不需要在Java的内存中拥有数百条(如果不是数千条)记录,而只需要十条左右。换句话说,如果你从未使用和/或论证过该方法,那么你很可能完全错误地接近它。LazyDataModelLIMITOFFSETfirstpageSizeload()


答案 2

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

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

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

    ...
}

推荐