for
: pour cibler l'id du champ concerné.xxxClass
: pour permettre de donner une classe CSS particulière lors de l'affichage du message généré et selon la criticité (errorClass, fatalClass, infoClass, warnClass).xxxStyle
: pour permettre de donner un style CSS particulier lors de l'affichage du message généré généré et selon la criticité (styleClass, styleClass, styleClass, styleClass).new FacesMessage( FacesMessage.SEVERITY_ERROR, EMAIL_EXISTE_DEJA, null ) );
<h:message>
ailleurs dans la page.<h:messages globalOnly="true" />
)<h:inputText id="email" value="#{inscrireBean.utilisateur.email}" requiredMessage="Veuillez saisir une adresse email" />
<h:inputSecret id="motdepasse" value="#{inscrireBean.utilisateur.motDePasse}" requiredMessage="Veuillez saisir un mot de passe" />
<h:inputSecret id="confirmation" value="#{inscrireBean.utilisateur.motDePasse}" requiredMessage="Veuillez saisir la confirmation du mot de passe" />
<h:inputText id="nom" value="#{inscrireBean.utilisateur.nom}" requiredMessage="Veuillez saisir un nom d'utilisateur" />
## Validation depuis la vue avec message d'erreur dans un blundle :
### Le blundle :
inscription.email = Veuillez saisir une adresse email
inscription.motdepasse = Veuillez saisir un mot de passe
inscription.confirmation = Veuillez saisir la confirmation du mot de passe
inscription.nom = Veuillez saisir un nom d'utilisateur
### La vue :
<!-- On charge le bundle à la vue est on l'assigne à la variable msg -->
<h:head>
...
<f:loadBundle basename="com.sdzee.bundle.messages" var="msg"/>
</h:head>
<!-- On utilise la variable de vue msg dans l'attribut requiredMessage -->
<h:inputText id="email" value="#{inscrireBean.utilisateur.email}" ... requiredMessage="#{msg['inscription.email']}" />
<h:inputSecret id="motdepasse" value="#{inscrireBean.utilisateur.motDePasse}" ... requiredMessage="#{msg['inscription.motdepasse']}" />
<h:inputSecret id="confirmation" value="#{inscrireBean.utilisateur.motDePasse}" ... requiredMessage="#{msg['inscription.confirmation']}" />
<h:inputText id="nom" value="#{inscrireBean.utilisateur.nom}" ... requiredMessage="#{msg['inscription.nom']}" />
event
: qui nous permet de définir l'action déclenchant l'envoi de la requête AJAX au serveur.render
: qui nous permet de définir le ou les composants dont le rendu doit être effectué, une fois la requête traitée par le serveur.execute
: permet de définir la portée de l'action à effectuer.<h:inputText id="email" value="#{inscrireBean.utilisateur.email}" required="true" size="20" maxlength="60" requiredMessage="#{msg['inscription.email']}">
<f:ajax event="blur" render="emailMessage" />
</h:inputText>
<h:message id="emailMessage" for="email" errorClass="erreur" />
En précisant @form dans l'attribut render, nous nous assurons ainsi que tout le formulaire va être actualisé lors d'un clic sur le bouton d'envoi.
<h:form id="formulaireUser">
<h:commandButton value="Inscription" action="#{inscrireBean.inscrire}" styleClass="sansLabel">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
</h:form>
Le validateur sera le même que le Validateur de comparaison de plusieurs champs dans Validation métier au dessus.
<h:outputLabel for="motdepasse">Mot de passe <span class="requis">*</span></h:outputLabel>
<h:inputSecret id="motdepasse" value="#{inscrireBean.utilisateur.motDePasse}" binding="#{composantMotDePasse}" size="20" maxlength="20">
<f:ajax event="blur" execute="motdepasse confirmation" render="motDePasseMessage confirmationMessage" />
</h:inputSecret>
<h:message id="motDePasseMessage" for="motdepasse" errorClass="erreur" />
<br />
<h:outputLabel for="confirmation">Confirmation du mot de passe <span class="requis">*</span></h:outputLabel>
<h:inputSecret id="confirmation" value="#{inscrireBean.utilisateur.motDePasse}" size="20" maxlength="20">
<f:ajax event="blur" execute="motdepasse confirmation" render="motDePasseMessage confirmationMessage" />
<f:attribute name="composantMotDePasse" value="#{composantMotDePasse}" />
<f:validator validatorId="confirmationMotDePasseValidator" />
</h:inputSecret>
<h:message id="confirmationMessage" for="confirmation" errorClass="erreur" />
<br />
validate()
, c'est elle qui va contenir le code métier chargé d'effectuer le contrôle de l'existence de l'adresse dans la base.@FacesValidator
qui permet de déclarer auprès du framework un objet comme étant un Validator, et permet ainsi de rendre cet objet accessible depuis une balise dans nos Facelets.@FacesValidator
. Pour pouvoir injecter EJB il faudra remplacer @FacesValidator
par les annotations @ManagedBean
et @RequestScoped
sur le validator puis remplacer sur la vue <f:validator validatorId="#{validatorName}" />
par <f:validator binding="#{validatorName}" />
package com.jsf.validators;
@FacesValidator(value = "validatorName")
public class ValidatorName implements Validator {
@Override
public void validate(FacesContext context, UIComponent component, Object value ) throws ValidatorException {
...
}
}
@ManagedBean
@RequestScoped
public class ExistenceEmailValidator implements Validator {
private static final String EMAIL_EXISTE_DEJA = "Cette adresse email est déjà utilisée";
@EJB
private UtilisateurDaoutilisateurDao;
@Override
public void validate( FacesContext context, UIComponent component, Object value ) throws ValidatorException {
/* Récupération de la valeur à traiter depuis le paramètre value */
String email = (String) value;
try {
if ( utilisateurDao.trouver( email ) != null ) {
/*
* Si une adresse est retournée, alors on envoie une exception
* propre à JSF, qu'on initialise avec un FacesMessage de
* gravité "Erreur" et contenant le message d'explication. Le
* framework va alors gérer lui-même cette exception et s'en
* servir pour afficher le message d'erreur à l'utilisateur.
*/
throw new ValidatorException(
new FacesMessage( FacesMessage.SEVERITY_ERROR, EMAIL_EXISTE_DEJA, null ) );
}
} catch ( DAOException e ) {
/*
* En cas d'erreur imprévue émanant de la BDD, on prépare un message
* d'erreur contenant l'exception retournée, pour l'afficher à
* l'utilisateur ensuite.
*/
FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_ERROR, e.getMessage(), null );
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage( component.getClientId( facesContext ), message );
}
}
}
...
<h:outputLabel for="motdepasse">Mot de passe <span class="requis">*</span></h:outputLabel>
<h:inputSecret id="motdepasse" value="#{inscrireBean.utilisateur.motDePasse}" binding="#{composantMotDePasse}" size="20" maxlength="20" />
<h:message id="motDePasseMessage" for="motdepasse" errorClass="erreur" />
<br />
<h:outputLabel for="confirmation">Confirmation du mot de passe <span class="requis">*</span></h:outputLabel>
<h:inputSecret id="confirmation" value="#{inscrireBean.utilisateur.motDePasse}" size="20" maxlength="20">
<h:message id="confirmationMessage" for="confirmation" errorClass="erreur" />
<br />
...
@FacesValidator( value = "confirmationMotDePasseValidator" )
public class ConfirmationMotDePasseValidator implements Validator {
private static final String CHAMP_MOT_DE_PASSE = "composantMotDePasse";
private static final String MOTS_DE_PASSE_DIFFERENTS = "Le mot de passe et la confirmation doivent être identiques.";
@Override
public void validate( FacesContext context, UIComponent component, Object value ) throws ValidatorException {
// Récupération de l'attribut mot de passe parmi la liste des attributs du composant confirmation
UIInput composantMotDePasse = (UIInput) component.getAttributes().get( CHAMP_MOT_DE_PASSE );
// Récupération de la valeur du champ, c'est-à-dire le mot de passe saisi
String motDePasse = (String) composantMotDePasse.getValue();
// Récupération de la valeur du champ confirmation
String confirmation = (String) value;
// Envoi d'une exception contenant une erreur de validation JSF initialisée avec le message destiné à l'utilisateur, si les mots de passe sont différents
if ( confirmation != null && !confirmation.equals( motDePasse ) ) {
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, MOTS_DE_PASSE_DIFFERENTS, null ));
}
}
}
@Entity
public class Utilisateur {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
@NotEmpty( message = "Veuillez saisir une adresse email" )
@Pattern( regexp = "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)", message = "Merci de saisir une adresse mail valide" )
private String email;
@Column( name = "mot_de_passe" )
@NotNull( message = "Veuillez saisir un mot de passe" )
@Size( min = 3, message = "Le mot de passe doit contenir au moins 3 caractères" )
private String motDePasse;
@NotNull( message = "Veuillez saisir un nom d'utilisateur" )
@Size( min = 3, message = "Le nom d'utilisateur doit contenir au moins 3 caractères" )
private String nom;
@Column( name = "date_inscription" )
private Timestamp dateInscription;
...
}
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>