title: JSF custom Validator : no message rendered
body: <p>I want to display an error message using a custom JSF Validator.</p>
  
  <p>After validation, I have no message rendered !</p>
  
  <p><strong>EDITED</strong></p>
  
  <p>I added more xHTML code, I have a popup with many fields and an <code>a4j:commandButton</code>.</p>
  
  <p>The xHTML</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:sec="http://www.springframework.org/security/facelets/tags"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:rich="http://richfaces.org/rich"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:fn="http://java.sun.com/jsp/jstl/functions"&gt;
  &lt;body&gt;
      &lt;script
          src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"&gt;&lt;/script&gt;
      &lt;ui:composition&gt;
          &lt;h:form&gt;
              &lt;ui:debug hotkey="x" /&gt;
              &lt;h:panelGrid width="100%"
                  rendered="#{not empty declarationReglementaireModel.detailCurrentDecReg.decReg.listLigneDipRecsDTO}"&gt;
  
                  &lt;rich:extendedDataTable id="listDipRec"
                      iterationStatusVar="itDipRec" rows="50"
                      value="#{declarationReglementaireModel.ligneDipRec}"
                      var="ligneDipRec" frozenColumns="1"
                      style="height:300px; width:900px;" selectionMode="none"&gt;
  
                      &lt;rich:column width="35px"&gt;
                          &lt;h:panelGrid columns="1" cellpadding="2"&gt;
                              &lt;a4j:commandLink render="editGridDipRec" execute="@this"
                                  oncomplete="#{rich:component('modifDipRec')}.show()"&gt;
                                  &lt;span class="icone icone-edit icone-align-center" /&gt;
                                  &lt;a4j:param value="#{itDipRec.index}"
                                      assignTo="#{declarationReglementaireModel.currentLigneDipRecIndex}" /&gt;
                                  &lt;f:setPropertyActionListener
                                      target="#{declarationReglementaireModel.currentLigneDipRec}"
                                      value="#{ligneDipRec}" /&gt;
                              &lt;/a4j:commandLink&gt;
  
                          &lt;/h:panelGrid&gt;
                      &lt;/rich:column&gt;
  
                      &lt;rich:column&gt;
                          &lt;f:facet name="header"&gt;
                              &lt;h:outputText value="F106" /&gt;
                          &lt;/f:facet&gt;
                          &lt;h:outputText value="#{ligneDipRec.lbValeurRubriqueF106}"&gt;
                          &lt;/h:outputText&gt;
                      &lt;/rich:column&gt;
  
                  &lt;/rich:extendedDataTable&gt;
              &lt;/h:panelGrid&gt;
  
  
              &lt;rich:popupPanel header="Données modifiables" id="modifDipRec"
                  domElementAttachment="form" autosized="true" zindex="500"
                  left="auto" top="auto"&gt;
                  &lt;h:panelGrid columns="1" id="editGridDipRec"&gt;
  
                      &lt;h:panelGrid columns="6" cellspacing="10"
                          styleClass="criteresSaisie" rowClasses="critereLigne"
                          columnClasses="titreCourtColonne,,titreCourtColonne,,titreCourtColonne,"&gt;
                          &lt;h:outputLabel for="DipRecDtLigne" value="Date ligne fichier Dip " /&gt;
                          &lt;h:outputText id="DipRecDtLigne"
                              value="#{declarationReglementaireModel.currentLigneDipRec.dtLigneDipRec}"&gt;
                              &lt;f:convertDateTime pattern="dd/MM/yyyy" timeZone="Europe/Paris" /&gt;
                          &lt;/h:outputText&gt;
  
  
  
                          &lt;h:outputLabel for="DipRecLbF106" value="F106 " /&gt;
                          &lt;h:inputText id="DipRecLbF106"
                              value="#{declarationReglementaireModel.currentLigneDipRec.lbValeurRubriqueF106}"&gt;
                              &lt;f:validator validatorId="checkvalidedouble" /&gt;
                          &lt;/h:inputText&gt;
                          &lt;h:messages id="DipRecLbF106_message" for="DipRecLbF106" /&gt;
  
  
                      &lt;/h:panelGrid&gt;
  
                      &lt;h:panelGroup&gt;
                          &lt;div align="right"&gt;
                              &lt;h:panelGrid columns="8"&gt;
                                  &lt;a4j:commandButton value="Enregistrer"
                                      action="#{rechercheDecRgltCtrl.enregistrerLigneDipRec}"
                                      render="listDipRec DipRecLbF106_message" execute="modifDipRec"
                                      oncomplete="if (#{facesContext.maximumSeverity==null}) {#{rich:component('modifDipRec')}.hide();}" /&gt;
                                  &lt;a4j:commandButton value="Annuler"
                                      onclick="#{rich:component('modifDipRec')}.hide(); return false;" /&gt;
                              &lt;/h:panelGrid&gt;
                          &lt;/div&gt;
                      &lt;/h:panelGroup&gt;
                  &lt;/h:panelGrid&gt;
  
              &lt;/rich:popupPanel&gt;
          &lt;/h:form&gt;
      &lt;/ui:composition&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>The Validator</p>
  
  <pre><code>public void validate(FacesContext facesContext, UIComponent uIComponent, Object object) throws ValidatorException{
      String enteredValue = (String)object;
      if(enteredValue.contains(",")){
          enteredValue = enteredValue.replace(",", ".") ;
      }
      boolean isANumber = false;
      try {  
          double d = Double.parseDouble(enteredValue);
          isANumber = true;
      }catch(NumberFormatException nfe) {  
          isANumber = false;
      }
      if (isANumber == false) {
          FacesMessage msgErreur = new FacesMessage("La valeur n'est pas un nombre valide.") ;
          msgErreur.setSeverity(FacesMessage.SEVERITY_ERROR) ;
          facesContext.addMessage(null, msgErreur) ;
          throw new ValidatorException(msgErreur);
      }
  }
  </code></pre>
  
  <p>faces-config</p>
  
  <pre><code>&lt;validator&gt;
    &lt;validator-id&gt;checkvalidedouble&lt;/validator-id&gt;
    &lt;validator-class&gt;xx.xxx.xxxxxx.model.DoubleValidator&lt;/validator-class&gt;
   &lt;/validator&gt;
  </code></pre>