web-dev-qa-db-fra.com

Comment afficher les erreurs de mon application dans JSF?

Dans mon application JSF/Facelets, voici une version simplifiée d'une partie de mon formulaire:

<h:form id="myform">
  <h:inputSecret value="#{createNewPassword.newPassword1}" id="newPassword1" />
  <h:message class="error" for="newPassword1" />
  <h:inputSecret value="#{createNewPassword.newPassword2}" id="newPassword2" />
  <h:message class="error" for="newPassword2" />
  <h:commandButton value="Continue" action="#{createNewPassword.continueButton}" />
</h:form>

J'aimerais pouvoir attribuer une erreur à une balise de message h: spécifique en fonction de quelque chose qui se passe dans la méthode continueButton (). Différentes erreurs doivent être affichées pour newPassword et newPassword2. Un validateur ne fonctionnera pas vraiment, car la méthode qui fournira des résultats (à partir de la base de données) est exécutée dans la méthode continueButton () et est trop coûteuse pour une exécution double. 

Je ne peux pas utiliser la balise h: messages car la page comporte plusieurs emplacements pour lesquels je dois afficher différents messages d'erreur. Quand j'ai essayé ceci, la page a affiché des doublons de chaque message.

J'ai essayé ceci comme une meilleure estimation, mais pas de chance:

public Navigation continueButton() {
  ...
  expensiveMethod();
  if(...) {
    FacesContext.getCurrentInstance().addMessage("newPassword", new FacesMessage("Error: Your password is NOT strong enough."));
  }
}

Qu'est-ce que je rate? Toute aide serait appréciée!

38
Eric Noob

Au cas où quelqu'un serait curieux, j'ai pu comprendre cela en fonction de toutes vos réponses combinées!

Ceci est dans le Facelet:

<h:form id="myform">
  <h:inputSecret value="#{createNewPassword.newPassword1}" id="newPassword1" />
  <h:message class="error" for="newPassword1" id="newPassword1Error" />
  <h:inputSecret value="#{createNewPassword.newPassword2}" id="newPassword2" />
  <h:message class="error" for="newPassword2" id="newPassword2Error" />
  <h:commandButton value="Continue" action="#{createNewPassword.continueButton}" />
</h:form>

C'est dans la méthode continueButton ():

FacesContext.getCurrentInstance().addMessage("myForm:newPassword1", new FacesMessage(PASSWORDS_DONT_MATCH, PASSWORDS_DONT_MATCH));

Et il fonctionne! Merci pour l'aide!

24
Eric Noob

FacesContext.addMessage (String, FacesMessage) requiert le clientId du composant, pas c'est id. Si vous vous demandez pourquoi, pensez à avoir un contrôle enfant dans un dataTable, en marquant différentes valeurs avec le même contrôle pour chaque ligne - il serait possible de faire imprimer un message différent pour chaque ligne. Le id est toujours le même; clientId est unique par ligne.

Donc, "myform: mybutton" est la valeur correcte, mais coder en dur est déconseillé. Une recherche créerait moins de couplage entre la vue et la logique métier et constituerait une approche qui fonctionne dans des environnements plus restrictifs tels que les portlets.

<f:view>
  <h:form>
    <h:commandButton id="mybutton" value="click"
      binding="#{showMessageAction.mybutton}"
      action="#{showMessageAction.validatePassword}" />
    <h:message for="mybutton" />
  </h:form>
</f:view>

Logique de haricot gérée:

/** Must be request scope for binding */
public class ShowMessageAction {

    private UIComponent mybutton;

    private boolean isOK = false;

    public String validatePassword() {
        if (isOK) {
            return "ok";
        }
        else {
            // invalid
            FacesMessage message = new FacesMessage("Invalid password length");
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(mybutton.getClientId(context), message);
        }
        return null;
    }

    public void setMybutton(UIComponent mybutton) {
        this.mybutton = mybutton;
    }

    public UIComponent getMybutton() {
        return mybutton;
    }
}
57
McDowell

Vous devez également inclure le FormID dans votre appel à addMessage ().

 FacesContext.getCurrentInstance().addMessage("myform:newPassword1", new FacesMessage("Error: Your password is NOT strong enough."));

Cela devrait faire l'affaire.

Cordialement.

6
huo73

Rappelez-vous que:

FacesContext context = FacesContext.getCurrentInstance();
context.addMessage( null, new FacesMessage( "The message to display in client" ));            

est également valide, car lorsque null est spécifié comme premier paramètre, il est appliqué à l'ensemble du formulaire.

Plus d'infos: coreservlets.com // périmé

3
InfZero

JSF est une bête. Il se peut que quelque chose me manque, mais j'avais l'habitude de résoudre des problèmes similaires en enregistrant le message souhaité dans une propriété du bean, puis en affichant cette propriété via un outputText

<h:outputText
    value="#{CreateNewPasswordBean.errorMessage}"
    render="#{CreateNewPasswordBean.errorMessage != null}" />
2
Jan Zich

Trouvé ceci en recherchant Google. Le deuxième message fait un point sur les différentes phases de JSF, ce qui pourrait entraîner la perte de votre message d'erreur. Aussi, essayez null à la place de "newPassword" car vous n'avez aucun objet avec l'id newPassword.

1
kevindaub

J'ai essayé ceci comme une meilleure estimation, mais pas de chance:

Cela me semble juste. Avez-vous essayé de définir une gravité de message explicitement? De plus, j’estime que l’ID doit être identique à celui d’un composant (c’est-à-dire que vous devez utiliser newPassword1 ou newPassword2, s’il s’agit de vos ID et non de newPassword comme dans l’exemple).

FacesContext.getCurrentInstance().addMessage("newPassword1", 
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error Message"));

Utilisez ensuite <h:message for="newPassword1" /> pour afficher le message d'erreur sur la page JSF.

1
user7094

Réponse simple, si vous n'avez pas besoin de le lier à un composant spécifique ... 

Java:

            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Authentication failed", null);
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, message);      

XHTML:

            <h:messages></h:messages>