2008-11-04 15 views
1

J'ai une application JSF qui se compose de deux JSP: login.jsp & main.jsp.JSF commandeLink action tir avant la mise à jour des valeurs de modèle

J'ai les suivantes faces-config.xml:

<lifecycle> 
    <phase-listener>package.programs.scorecard.beans.EventBean</phase-listener> 
</lifecycle> 
<managed-bean> 
    <managed-bean-name>FormBean</managed-bean-name> 
    <managed-bean-class>package.programs.scorecard.beans.FormBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
</managed-bean> 
<managed-bean> 
    <managed-bean-name>DataBean</managed-bean-name> 
    <managed-bean-class>package.programs.scorecard.beans.DataBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
</managed-bean> 
<managed-bean> 
    <managed-bean-name>EventBean</managed-bean-name> 
    <managed-bean-class>package.programs.scorecard.beans.EventBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
</managed-bean> 

Et le web.xml suivant:

<welcome-file-list> 
    <welcome-file>faces/login.jsp</welcome-file> 
    <welcome-file>faces/index.jsp</welcome-file> 
    <welcome-file>index.jsp</welcome-file> 
</welcome-file-list> 
<servlet> 
    <servlet-name>Faces Servlet</servlet-name> 
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
    <servlet-name>Faces Servlet</servlet-name> 
    <url-pattern>/faces/*</url-pattern> 
</servlet-mapping> 

J'ai deux ou trois composants sur Login.jsp que les propriétés de mise à jour à Databean sur un lien commandLink. En cas de réussite, l'utilisateur est dirigé vers /main.jsp.

Je remarque que lorsque je clique sur le lienCommande, la méthode s'exécute AVANT que le bean ne soit mis à jour. Cela a pour résultat que toutes mes propriétés de bean sont nulles lorsque la méthode s'exécute car les valeurs de mon formulaire ne sont pas appliquées au bean. D'après ce que j'ai compris du cycle de vie JSF, les «Valeurs du modèle de mise à jour» doivent toujours être exécutées avant «Invoke Application», sauf si «immediate = true» est spécifié, ce qui n'est pas le cas pour ma commande commandLink.

J'ai essayé de déboguer cela pendant quelques heures ce matin, et je me réjouis de toutes suggestions ou idées.

MISE À JOUR: J'ai étudié cette question à fond et ont conclu que le menu déroulant composante I utilisait a un bogue qui devrait être fixé dans la prochaine version. Ma solution a été d'utiliser un h normal: selectOneMenu au lieu du composant tiers, et cela fonctionne comme un charme:

<h:selectOneMenu id="ddlManager" value="#{DataBean.managerId}"> 
    <f:selectItems value="#{DataBean.managerList}" /> 
</h:selectOneMenu> 

Où managerList est une liste d'objets selectItem.

+0

Pourriez-vous fournir un peu plus d'explications. Voulez-vous dire que la méthode pagecode pour le lien de commande est en cours d'exécution avant que votre phaselistener ne soit appelé? Avez-vous une logique quelconque dans votre phaselistener qui pourrait l'empêcher d'être appelé? – BoboTheCodeMonkey

Répondre

2

Ceci n'est pas une solution - c'est un exemple qui pourrait vous aider à diagnostiquer le problème. Bien sûr, vous pouvez déjà le faire - je vois que vous avez implémenté un écouteur de phase.

Bean:

public class LoginBean implements Serializable { 

    private String user; 
    private String password; 

    public String getPassword() { 
     return password; 
    } 

    public String getUser() { 
     return user; 
    } 

    public void setPassword(String password) { 
     System.out.println("Update Password: " + password); 
     this.password = password; 
    } 

    public void setUser(String user) { 
     System.out.println("Update User: " + user); 
     this.user = user; 
    } 

    public String login() { 
     if ("user".equals(user) && "password".equals(password)) { 
      // ok 
      System.out.println("Login OK"); 
      return "loggedIn"; 
     } else { 
      System.out.println("Login Failed"); 
      FacesContext context = FacesContext.getCurrentInstance(); 
      FacesMessage message = new FacesMessage(
        "Invalid user name or password"); 
      context.addMessage(null, message); 
      return null; 
     } 
    } 

} 

Vue:

<f:view> 
    <h:form> 
     login: 
     <h:inputText value="#{loginBean.user}" /> 
     <h:inputSecret value="#{loginBean.password}" /> 
     <h:commandButton value="login" action="#{loginBean.login}" /> 
     <h:messages /> 
    </h:form> 
</f:view> 

faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?> 

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" 
    version="1.2"> 
    <managed-bean> 
     <managed-bean-name>loginBean</managed-bean-name> 
     <managed-bean-class>login.LoginBean</managed-bean-class> 
     <managed-bean-scope>session</managed-bean-scope> 
    </managed-bean> 
    <navigation-rule> 
     <display-name>login</display-name> 
     <from-view-id>/login.jsp</from-view-id> 
     <navigation-case> 
      <from-outcome>loggedIn</from-outcome> 
      <to-view-id>/label.jsp</to-view-id> 
     </navigation-case> 
    </navigation-rule> 
    <lifecycle> 
     <phase-listener>login.PhaseListenerImpl</phase-listener> 
    </lifecycle> 
</faces-config> 

auditeur de phase:

public class PhaseListenerImpl implements PhaseListener { 

    public void afterPhase(PhaseEvent event) { 
     System.out.println("AFTER: " + event.getPhaseId()); 
    } 

    public void beforePhase(PhaseEvent event) { 
     System.out.println("BEFORE: " + event.getPhaseId()); 
    } 

    public PhaseId getPhaseId() { 
     return PhaseId.ANY_PHASE; 
    } 

} 

La sortie de journal attendue pour un nom d'utilisateur et un mot de passe correspondants serait:

BEFORE: RESTORE_VIEW(1) 
AFTER: RESTORE_VIEW(1) 
BEFORE: APPLY_REQUEST_VALUES(2) 
AFTER: APPLY_REQUEST_VALUES(2) 
BEFORE: PROCESS_VALIDATIONS(3) 
AFTER: PROCESS_VALIDATIONS(3) 
BEFORE: UPDATE_MODEL_VALUES(4) 
Update User: user 
Update Password: password 
AFTER: UPDATE_MODEL_VALUES(4) 
BEFORE: INVOKE_APPLICATION(5) 
Login OK 
AFTER: INVOKE_APPLICATION(5) 
BEFORE: RENDER_RESPONSE(6) 
AFTER: RENDER_RESPONSE(6) 
+0

Merci, @McDowell. Voir la question mise à jour ... J'ai découvert que la solution était dans le composant que j'utilisais. J'ai suivi vos conseils et j'ai traversé tout le cycle de la vie sans pouvoir m'en rendre compte. Merci mon ami. – karlgrz