2016-04-01 11 views
4

Edit: Der Kommentar Abschnitt löste mein Problem! Das Problem war, dass ich falsche Importe für die Bereiche verwendete.Nach der Migration von JSF @ManagedBean zu CDI @Named, Konstruktor mehrmals aufgerufen und Eingabewerte immer Null

Ich habe eine einfache JSF-Anwendung (Login, Daten aus der Datenbank ziehen, erlauben Benutzer Daten zu bearbeiten). Es funktioniert gut, ich möchte den Code aktualisieren, um CDI (Weld) zu verwenden, aber ich habe Probleme. Ich verfolge/betrachten: http://docs.jboss.org/weld/reference/latest/en-US/html/example.html Original-Material ohne Weld:

login.xhtml

<h:form id="inputForm"> 
    <h:panelGrid columns="2" cellpadding="5" cellspacing="1"> 
     <h:outputText id="nameDesc" value="Name"></h:outputText> 
     <h:inputText id="nameInput" value="#{login.loginName}" binding="#{name}"></h:inputText> 

     <h:outputText id="passwordDesc" value="Password"></h:outputText> 
     <h:inputSecret id="passwordInput" value="#{login.password}" binding="#{password}"></h:inputSecret> 

    </h:panelGrid> 
    <h:commandButton value="Login" action="#{login.login(name.value, password.value)}"/> 
</h:form> 

LoginBean.java:

@ManagedBean(name="login") 
@SessionScoped 
public class LoginBean implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @ManagedProperty(value="#{db}") 
    private DatabaseBean db; 
    private String password; 
    private String loginName; 
    // other stuff and functions 

    public String getLoginName() { 
     return loginName; 
    } 

    public void setLoginName (String name) { 
     this.loginName = name; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword (final String password) { 
     this.password = password; 
    } 

    public void setDb(DatabaseBean db) { 
     this.db = db; 
    } 

DatabaseBean.java:

@ManagedBean(name="db", eager=true) 
@ApplicationScoped 
public class DatabaseBean implements Serializable { 
@PostConstruct 
    public void init() { 
     //... connect to database etc 
    }  

}

--------- Was ich versucht habe, es mit Weld laufen zu lassen (nur Änderungen von oben, um es ein bisschen kürzer zu machen): -------- LoginBean.java, geändert zu @Inject für DatabaseBean

@Named("login") 
@SessionScoped 
public class LoginBean implements Serializable { 
    // stuff 
     private @Inject DatabaseBean db; 
} 

DatabaseBean.java, geändert @Named von @ManagedBean @Named aus @ManagedBean, hinzugefügt:

public String login(String name, String password) { 
    System.out.println("login called"+name); 
    // other stuff 

} 
:

@Named("db") 
@ApplicationScoped 
public class DatabaseBean implements Serializable { 
} 

LoginBean eine Funktion hat,

Mit meiner zweiten Implementierung (der, wo ich versuche, Weld zu verwenden), wird der Ausdruck einmal aufgerufen: "Login aufgerufen", und der Benutzername ist leer (ich überprüft dies mit name.IsEmpty()).

ich auch versucht haben, es durch Konstruktor Injektion:

loginBean.java

@Inject 
public LoginBean(DatabaseBean db) { 
    System.out.println("constructor"); 
    this.db = db; 
} 

Als ich dies die ich von „Konstruktor“ druckt bekommen viel zu tun, so ist es mehrmals angerufen, aber ich Ich verstehe nicht, warum - ich denke, das ist das Problem obwohl, nur eine Instanz von LoginBean bekommt die Eingabe (Benutzername und Passwort) und dann viele neue werden aus irgendeinem Grund erstellt. Warum das?

Ich benutze Eclipse und Tomcat8, um es zu starten. Vielen Dank für das Lesen!

+1

Und welche '@ SessionScoped' Sie sollten die richtige auch dafür verwenden. –

+0

Hallo, danke für die Antworten! Meine sessionscoped: import javax.faces.bean.SessionScoped; – Lomtrur

+1

Wenn Sie CDI verwenden, müssen Sie die CDI-Bereiche ** nicht ** die JSF-Bereiche verwenden. –

Antwort

2

Managed Bean Konstruktor mehrmals aufgerufen

CDI kann Konstruktor aufrufen häufiger zu erwarten als beim Generieren/Erstellen von erweiterten Unterklassen/Proxies. Siehe auch Field.get(obj) returns all nulls on injected CDI managed beans, while manually invoking getters return correct values. Loggen Sie den Konstruktoraufruf einfach nicht ein, es würde Sie nur verwirren. @PostConstruct ist die einzige interessante Methode, um anzuhaken.


der Druck wird einmal aufgerufen: „login genannt“, und der Benutzername leer ist (Ich habe dies mit Namen.Ist leer()).

In Bezug auf die konkrete Problem der Form Werte Eingangs null ist, wenn die Aktion-Methode aufgerufen wird, und damit die @SessionScoped CDI Managed Bean scheinbar bei jedem Zugriff neu erstellt wird, passt das das Verhalten eines @Dependent Bohne scoped. Dies ist der Standardbereich, wenn kein gültiger CDI-Bean-Bereich gefunden werden kann. Siehe auch What is the default Managed Bean Scope in a JSF 2 application?

Dies wiederum schlägt vor, dass Sie @SessionScoped aus dem falschen Paket importiert. Stellen Sie sicher, dass es aus dem Paket javax.enterprise.context stammt und nicht aus z. javax.faces.bean. JSF-gesteuerte Bean-Bereiche sind nicht als gültige CDI-gesteuerte Bean-Bereiche erkennbar.

import javax.inject.Named; 
import javax.enterprise.context.SessionScoped; 

@Named("login") 
@SessionScoped 
public class LoginBean implements Serializable { 
    // ... 
}