0 Replies Latest reply on Jul 18, 2011 9:50 AM by hombre2k

    Problem with custom Converter and Validator

    hombre2k

      Hello,


      i'm trying to implement a custom Converter and Validator for an h:selectOneRadio component with wich the user can select the language of a document. The Classes Document and Language are Entities, language is a property of the document. Both, the Converter and the Validator, seem to work, because the output in the logfile looks good. But instead of executing the form the faces-message value is not valid (javax.faces.component.UISelectOne.INVALID) is shown.


      The code for the components is shown below.


      Here is the part of the form:


      <s:decorate id="languageField" template="layout/edit.xhtml" rendered="true">
          <ui:define name="label">#{messages.language}</ui:define>
          <h:selectOneRadio id="documentLanguage" 
                                layout="pageDirection"
                                value="#{documentHandler.language}"
                                converter="LanguageConverter"
                                validator="LanguageValidator">
              <f:selectItems value="#{availableLanguages}"/>
          </h:selectOneRadio>
      </s:decorate>
      



      The Converter Class:


      @Name("LanguageConverter") 
      @BypassInterceptors 
      @Converter
      public class LanguageConverter implements javax.faces.convert.Converter {
              
              @Transactional
              public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
                      EntityManager entityManager = (EntityManager) Component.getInstance("entityManager");
                  entityManager.joinTransaction();
                  System.out.println("input language String = '" + arg2 + "'");
                  Integer id = Integer.parseInt(arg2);
                  
                      return entityManager.find(Language.class, id);
              }
      
              public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
                      if (arg2 instanceof Language) {
                              String languageString = ((Language) arg2).getId().toString();
                              System.out.println("returning language String = '" + languageString + "'");
                              return languageString;
                      }
                      System.out.println("Object arg2 not of type language");
                      return null;
              }
      }
      



      The Validator Class:


      @Name("LanguageValidator") 
      @BypassInterceptors 
      @org.jboss.seam.annotations.faces.Validator
      public class LanguageValidator implements javax.faces.validator.Validator {
      
              public void validate(FacesContext arg0, UIComponent arg1, Object arg2)
                              throws ValidatorException {
                      boolean valid = arg2 instanceof Language;
                    if (!valid) {
                        System.out.println("language '" + arg2.getClass().toString() + "' is not valid");
                       throw new ValidatorException(new javax.faces.application.FacesMessage("Invalid value " + arg2.getClass().toString()));
                    }
                    else {
                        System.out.println("language '" + arg2.getClass().toString() + "' is valid");
                    }
              }
      }
      
      



      The Factory Class which returns the Collection of SelectItems (the values are of type Language.class):


      @Name("availableLanguages")
      @Scope(org.jboss.seam.ScopeType.SESSION)
      public class AvailableLanguages implements Serializable {
              @Logger
              private Log log;
              
              @In EntityManager entityManager;
              
              private Collection<SelectItem> availableLanguages = null;
      
              @Unwrap
              public Collection<SelectItem> getAvailableLanguages() {
                      if (availableLanguages == null) {
                              init();
                      }
                      return availableLanguages;
              }
              
              @Observer(value="languagesChanged",create=false)
              public void init() {
                      log.info("executing method AvailableLanguages.init()");
                      if (availableLanguages == null) {
                              availableLanguages = new ArrayList<SelectItem>();
                      }
                      else {
                              availableLanguages.clear();
                      }
                      List<Language> languages = entityManager.createQuery("select l from Language l order by l.name ASC").getResultList();
                      for (int i = 0; i < languages.size(); i++) {
                              availableLanguages.add(new SelectItem(languages.get(i), 
                              new org.jboss.seam.international.Messages().getMessages().get(languages.get(i).getShortname())));
                      }
              }
      }
      



      The action-method of the form simply persists or merges the document Entity. When i open the view which contains the form, the selectOne form-element is shown correctly, but the language of the document is not checked (the document already has an language property saved in the database).
      the output in the logfile looks as follows:


      15:27:22,644 INFO  [STDOUT] returning language String = '1'
      15:27:22,645 INFO  [STDOUT] returning language String = '2'
      15:27:22,645 INFO  [STDOUT] returning language String = '3'
      



      This indicates that the getAsString()-method is executed 3 times correctly, there are 3 languages available.


      When i select a language in the form-element an click the submit-button the message value is not valid is rendered and in the following lines appear in the logfile:


      15:35:31,135 INFO  [STDOUT] input language String = '2'
      15:35:31,138 INFO  [STDOUT] language 'class org.something.entity.Language' is valid
      15:35:31,271 INFO  [STDOUT] returning language String = '1'
      15:35:31,271 INFO  [STDOUT] returning language String = '2'
      15:35:31,271 INFO  [STDOUT] returning language String = '3'
      



      The first line indicates that the Converter-method getAsObject() is executed successfully. the second line comes from the Validator. After that the form is rendered again, but this time with the error message.


      Has anyone an idea why this happens?


      Thanks in advance,
      Jan