2013-08-02 4 views
12

Ich denke, das Problem aufwirft, weil ich nicht etwas mit EJBs bekommen haben. Ich habe eine Serviceklasse für meine Entität, die @Stateless ist. Als ich es verwenden, indem Sie mit @EJB in meinem Sitzung scoped Präsentationsmodell injiziert, ist alles ok. Aber jetzt wollte ich diese EJB-Dienst verwenden in einem Datamodel I zur Verwendung in meinem Vortrag Modell überschrieben haben:Nullpointer wenn EJB in Java Injektion Klasse

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

Bei der Ausführung erhalte ich eine Nullpointer an Position „users = service.findAllUsers();“ Das gleiche funktioniert, wenn ich überschreibe dieses Datenmodell in meinem Vortrag Modell:

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

Ist es nicht möglich, ein EJB in einer normalen Java-Klasse zu injizieren? Was muss ich tun, dass ich das DataModel nicht im Präsentationsmodell definieren muss?

Dank

+0

Versuchen Sie, Ihr BeanInterface in die EJB-Anmerkung einzufügen. Ich habe das gleiche Problem vor einiger Zeit und das hat es behoben. '@EJB (beanInterface = YourInterface.class)' – ZeusNet

Antwort

13

EJBs sind nur in verwalteten Bohnen injiziert. Ein Bean verwaltet wird, wenn es durch einen Injektionsbehälter, wie zum Beispiel über JSF eigene @ManagedBean, CDI @Named usw. verwaltet werden können Sie auch ein EJB in einem anderen EJB injizieren. Sie können keine EJB in einer nicht verwalteten Klasse injizieren (man kann es von JNDI jedoch manuell greifen, aber das ist nur hässlich).

Sie haben grundsätzlich folgende Möglichkeiten:

  1. In @PostConstruct Ihrer verwalteten Bohne, konstruieren, um das Datenmodell, wobei Sie das Ergebnis als Argument übergeben (beachten Sie, dass dies auch, wie Standard-Datenmodelle wie ListDataModel Arbeit) .

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

  2. Machen LazyUserDataModel abstrakt, wobei Sie den Benutzer fragen, um das Ergebnis zu liefern.

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

    , so dass die anonyme Klasse schmerzt weniger

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

  3. LazyUserDataModel Machen Sie eine Managed Bean auch, und es stattdessen injizieren.

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

    mit

    @Inject 
    private LazyUserDataModel lazyUsers; 
    

  4. Erstellen einer vollwertigen anonyme Instanz wie als Sie dachten.


Unrelated auf die konkrete Problem, es hat keinen Sinn, einen LazyDataModel aufweist, wodurch Sie alle Aufzeichnungen zur Verfügung stellen. Seine Absicht ist, dass es Ihnen die Möglichkeit bietet, nur eine Teilmenge oder Datensätze mit SQL-Potenzen (LIMIT, OFFSET und Freunde) basierend auf dem aktuellen paginierten Status anzufordern, so dass Sie nicht Hunderte, wenn nicht Tausende Datensätze im Java-Speicher haben müssen nur zehn oder so. Mit anderen Worten, wenn Sie nie first und/oder pageSize Argument der load() Methode verwenden, nähern Sie sich höchstwahrscheinlich es völlig falsch.

+0

Danke für diese detaillierte Antwort @BalusC. Bevor ich das versuche, zu den beiden Off-Themen: Ich weiß, was das LazyDataModel auf diese Weise nicht sinnvoll macht. Ich wollte den Code nur so weit wie möglich vereinfachen. Aber was ich nicht wirklich verstehe, ist deine erste Aussage: In welchem ​​Konstruktor sollte der Dienst null sein? In "öffentliche UserPM()"? Wenn ich etwas nicht übersehen habe, dann funktioniert es genau so für mich. – timmornYE

+0

Injected-Abhängigkeiten sind im Konstruktor nicht verfügbar, aber frühestens in '@ PostConstruct', aus dem einfachen Grund, weil Instanzvariablen nicht gesetzt werden können, bevor die Instanz erstellt wird. – BalusC

+0

Lösung 4 sah für mich am schönsten aus und funktioniert! Vielen Dank! – timmornYE

2

Sie können nur Bohnen und EJBs innerhalb Bohnen und EJBs injizieren, die durch den Behälter erzeugt werden. Nicht in Objekte, die Sie selbst new mit instanziiert. Der Behälter ist nicht bewusst, die Objekte, die Sie instanziieren, und somit ist unfähig, etwas in diesen Objekten zu injizieren.

Also, lassen Sie einfach den Behälter instantiate und injizieren das LazyUserDataModel Objekt:

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

    ... 
}