15

我认为这个问题的出现是因为我没有得到 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; 
    }
}

执行时,我在“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?

谢谢

4

2 回答 2

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());
    }
    

  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一个托管 bean 并注入它。

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

    @Inject
    private LazyUserDataModel lazyUsers;
    

  4. 像你想象的那样创建一个成熟的匿名实例。


与具体问题无关,没有必要LazyDataModel提供所有记录。它的意图是它为您提供了基于当前分页状态使用 SQL 功能(和朋友)仅请求一个子集或记录的可能性,LIMIT因此OFFSET您不需要在 Java 内存中拥有数百甚至数千条记录,而只需十个或者。换句话说,如果您从不使用first和/或pageSizeload()方法的参数,那么您很可能完全错误地接近它。

于 2013-08-02T12:46:31.497 回答
4

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

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

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

    ...
}
于 2013-08-02T12:45:54.693 回答