web-dev-qa-db-ja.com

JavaクラスにEJBを挿入するときのNullPointerException

私は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を定義する必要がないようにするにはどうすればよいですか?

ありがとう

15
timmornYE

EJBは、マネージドBeanにのみ注入されます。 Beanは、JSF独自の_@ManagedBean_、CDIの_@Named_などを介して、何らかのインジェクションコンテナによって管理されている場合に管理されます。別のEJBにEJBをインジェクトすることもできます。アンマネージクラスにEJBを挿入することはできません(ただし、JNDIから手動で取得することはできますが、それは明らかに醜いです)。

基本的に次のオプションがあります。

  1. 管理対象Beanの_@PostConstruct_で、結果を引数として渡すデータモデルを構築します(これは、 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. あなたが考えたように、本格的な匿名インスタンスを作成します。


具体的な問題とは無関係allレコードを提供するLazyDataModelを持つ意味はありません。その目的は、現在のページ付けされた状態に基づいて、SQLパワー(LIMITOFFSETおよびその仲間)を使用してサブセットまたはレコードのみを要求する可能性を提供することです。 Javaのメモリには、数千とは言わないまでも数百のレコードがありますが、10程度しかありません。つまり、load()メソッドのfirstおよび/またはpageSize引数を使用したことがない場合は、完全に間違ったアプローチをしている可能性があります。

17
BalusC

コンテナによって作成されたBeanおよびEJB内にのみBeanおよびEJBを挿入できます。 newを使用して自分でインスタンス化するオブジェクトの内部ではありません。コンテナは、インスタンス化するオブジェクトを認識しないため、これらのオブジェクトに何も注入できません。

したがって、コンテナをインスタンス化してLazyUserDataModelオブジェクトを挿入するだけです。

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

    ...
}
4
JB Nizet