2013-08-02 22 views
12

Myślę, że ten problem nasila się, ponieważ nie dostałem czegoś z EJB. Mam klasę usług dla mojej jednostki, która jest @Stateless. Kiedy używam go poprzez wstrzykiwanie @EJB w moim modelu prezentacji o zasięgu sesji, wszystko jest w porządku. Ale teraz chciałem skorzystać z tej usługi EJB w DataModel Mam nadpisane do użytku w moim modelu PrezentacjaWyjątek NullPointerException podczas wstrzykiwania EJB w Java Klasa

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

Na wykonanie otrzymuję NullPointerException w pozycji „users = service.findAllUsers();” Te same prace, kiedy nadpisać ten DataModel w moim modelu prezentacji:

@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 ; 
       } 
     }; 
    } 
} 

nie jest to możliwe do wstrzykiwania EJB w normalnej klasy Java? Co muszę zrobić, że nie muszę definiować DataModel w modelu prezentacji?

Dzięki

+0

Spróbuj umieścić swój BeanInterface w adnotacji EJB. Mam ten sam problem kilka razy temu i to naprawiło. '@EJB (beanInterface = YourInterface.class)' – ZeusNet

Odpowiedz

13

EJB są wstrzykiwane jedynie w zarządzanych fasoli. Zarządzanie ziarnem jest zarządzane, gdy jest zarządzane przez jakiś pojemnik z wtryskiem, taki jak własny JSF @ManagedBean, CDI @Named itd. Można nawet wstrzyknąć EJB w innym EJB. Nie możesz wstrzyknąć EJB w klasie niezarządzanej (możesz jednak ręcznie pobrać ją z JNDI, ale to jest brzydkie).

Masz w zasadzie następujące opcje:

  1. W @PostConstruct zarządzanych fasoli, skonstruować datamodel czym przechodzą wynik jako argumentu (należy pamiętać, że jest to również jak standardowe modele danych jak ListDataModel pracy) .

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

  2. Bądź LazyUserDataModel streszczenie czym poprosić użytkownika o dostarczenie wynik.

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

    tak, że anonimowa klasa boli mniej

    lazyUsers = new LazyUserDataModel() { 
        @Override 
        public List<User> findAllUsers() { 
         return service.findAllUsers(); 
        } 
    }; 
    

  3. Bądź LazyUserDataModel zarządzany fasoli, jak również i wstrzyknąć go zamiast.

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

    z

    @Inject 
    private LazyUserDataModel lazyUsers; 
    

  4. Tworzenie fullfledged anonimowej instancji jak jak zorientowali.


niezwiązane do konkretnego problemu, nie ma sensu posiadania LazyDataModel którym podasz wszystkie rekordy. Jego intencją jest to, że oferuje ona możliwość żądania tylko podzbioru lub rekordów używających uprawnień SQL (LIMIT, OFFSET i przyjaciół) na podstawie bieżącego stanu w paginacji, aby nie trzeba było mieć setek, jeśli nie tysięcy rekordów w pamięci Java, ale tylko dziesięć lub więcej. Innymi słowy, jeśli nigdy nie używasz argumentu first i/lub pageSize metody load(), najprawdopodobniej podejdziesz do tego zupełnie źle.

+0

Dzięki za tę szczegółową odpowiedź @BalusC. Zanim spróbuję tego, do dwóch wyłączonych tematów: Wiem, co ten LazyDataModel nie ma sensu w ten sposób. Chciałem tylko uprościć kod tak bardzo, jak to możliwe. Ale to, czego nie rozumiem, to twoje pierwsze zdanie: w jakim konstruktorze usługa powinna być zerowa? W "public UserPM()"? Jeśli czegoś nie przeoczyłem, to dokładnie to działa dla mnie. – timmornYE

+0

Zależności iniekcyjne nie są dostępne w konstratorze, ale najwcześniej tylko w '@ PostConstruct', z tego prostego powodu, ponieważ zmiennych instancji nie można ustawić przed utworzeniem instancji. – BalusC

+0

Rozwiązanie 4 wyglądało najładniej i działa! Dzięki! – timmornYE

2

można wstrzyknąć tylko fasolę i EJBs wewnątrz fasoli i EJB, które są tworzone przez kontener. Nie wewnątrz obiektów, które tworzysz, używając new. Kontener nie jest świadomy obiektów, które tworzysz, a tym samym nie może wstrzyknąć niczego w te obiekty.

Więc po prostu niech instancję kontenera i wstrzyknąć obiekt LazyUserDataModel:

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

    ... 
} 
Powiązane problemy