2 Replies Latest reply on Apr 9, 2013 5:38 AM by blebleskeble

    Validation messages rendered multiple times after upload

    blebleskeble

      Hi. I am facing strange problem with combination of client side validation and file upload.

       

      On my page I have input with client side validation on blur event. When validation fails, message is correctly displayed by rich:messages component. then if I upload file via rich:fileUpload and trigger validation again, message is displayed twice. After next upload three times etc. Can anyone tell me what I am doing wrong? If i submit input via button, server validator is triggered and message is rendered only once regardless on how many files i have uploaded.

       

      (RF 4.2.0, myfaces 2.1.9, tomcat 7.0.30)

       

      here is my page:

       

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:a4j="http://richfaces.org/a4j"
          xmlns:rich="http://richfaces.org/rich">
      <h:head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          <title>Upload and Messages</title>
      </h:head>
      <h:body>
          <h:outputScript library="js" name="scripts.js" target="head" />
          <h:form id="myForm">
              <h:inputText id="inp" value="#{upload.inputString}" >
                  <f:validator validatorId="requiredValidator"/>
                  <rich:validator event="blur" />
              </h:inputText>
              <a4j:commandButton id="button" execute="inp" render="envelope" />
              <br />
              <a4j:outputPanel id="envelope">
                  <h:outputText value="#{upload.status}" />
                  <br />
                  <rich:fileUpload id="upload" fileUploadListener="#{upload.uploadListener}" >
                      <a4j:ajax event="uploadcomplete" render="envelope" />
                  </rich:fileUpload>
              </a4j:outputPanel>
          </h:form>
          <rich:popupPanel id="messagePopup" left="500" top="20" show="true" modal="false" >
              <rich:messages id="mess" />
          </rich:popupPanel>
      </h:body>
      </html>
      

       

      and here my managed bean

       

      package bleble.controller;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.Serializable;
      
      import javax.annotation.PostConstruct;
      import javax.faces.bean.ManagedBean;
      import javax.faces.bean.ViewScoped;
      
      import org.richfaces.event.FileUploadEvent;
      
      @SuppressWarnings("serial")
      @ManagedBean(name = "upload")
      @ViewScoped
      public class UploadController implements Serializable {
          
          private String inputString;
          
          private File f = null;
          private String status = "Waiting for file.";
          
          public UploadController() {
              
          }
      
          public void uploadListener(final FileUploadEvent event) {
              System.out.println("uploading");
              String filename = event.getUploadedFile().getName();
              try {
                  if (filename.contains("\\")) {
                          filename = filename.substring( event.getUploadedFile().getName().lastIndexOf("\\") + 1, event.getUploadedFile().getName().length());
                  }
                  f = File.createTempFile(filename , "");
                  FileOutputStream fos = new FileOutputStream(f);
                  FileInputStream fis = (FileInputStream) event.getUploadedFile().getInputStream();
      
                  byte buf[] = new byte[524288];
                  int len;
                  while ((len = fis.read(buf)) > 0) {
                      fos.write(buf, 0, len);
                  }
                  fos.close();
                  fis.close();
              } catch (IOException e1) {
                  
              } finally {
                  if (f != null) {
                      status = "File " + f.getName() + " uploaded.";
                  }
              }
          }
          
          public String getStatus() {
              return status;
          }
      
          public String getInputString() {
              return inputString;
          }
      
          public void setInputString(final String inputString) {
              this.inputString = inputString;
          }
      }
      

       

      this i my faces validator

       

      package bleble.validator;
      
      import java.io.Serializable;
      
      import javax.faces.component.UIComponent;
      import javax.faces.context.FacesContext;
      import javax.faces.validator.FacesValidator;
      import javax.faces.validator.Validator;
      import javax.faces.validator.ValidatorException;
      import javax.faces.application.FacesMessage;
      import javax.faces.application.ResourceDependency;
      
      @SuppressWarnings("serial")
      @FacesValidator(value = "requiredValidator")
      @org.richfaces.javascript.ClientSideScript(function = "validateMandatory", resources = @ResourceDependency(name = "scripts.js", library = "js", target = "head"))
      public class RequiredValidator implements Serializable, Validator {
          @Override
          public final void validate(final FacesContext context, final UIComponent component, final Object value) throws ValidatorException {
              FacesMessage message = new FacesMessage();
              message.setDetail("field is mandatory");
              message.setSummary("Validation failed: field is mandatory! (server)");
              message.setSeverity(FacesMessage.SEVERITY_ERROR);
              
              if (value == null || "".equals(value.toString().trim())) {
                  throw new ValidatorException(message);
              }
          }
      }
      

       

      and its client implementation in scripts.js

       

      function mymessage(summary, detail, severity){
          this.summary=summary;
          this.detail=detail; 
          this.severity=severity;
      }
      
      function validateMandatory(value, label, params, msg) {
          if (jQuery().trim(value) != "") {
              return;
          } else {
              var myMess = new mymessage("Validation failed: field is mandatory! (client)", "field is mandatory", 2);
              throw myMess;
          }
      }
      

       

      all files are also attached in archive

        • 1. Re: Validation messages rendered multiple times after upload
          sivaprasad9394

          Hello Pavel,

           

          As you know rich:messages will display all the message in the page not only one .

          <rich:popupPanel id="messagePopup" left="500" top="20" show="true" modal="false" >
                  <rich:messages id="mess" />
              </rich:popupPanel>


          try adding it to specific component like

           

            FacesContext faceContext = FacesContext.getCurrentInstance();

                    FacesMessage facesMessage = new FacesMessage();

                    facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);     

                    facesMessage.setDetail(this.ppsResources.getString("passwordupdated"));

                    facesMessage.setSummary(this.ppsResources.getString("passwordupdated"));

                    faceContext.addMessage("main:changepassview:changePassForm:updatedpasswordField", facesMessage);

           

               

          <h:outputText id="updatedpasswordField"/>

                        <h:message for="updatedpasswordField" errorClass="wf_error"></h:message>

           

          Thanks,

          Siva

          • 2. Re: Validation messages rendered multiple times after upload
            blebleskeble

            Hi Siva,

             

            adding of messages via FacesContext works as it should, but problem is that my validation is performed on client side, so using FacesContext is not possible.