Converter in JSF (PrimeFaces) with SelectOneMenu: Validation Error

15,697

In total I think you are on the right way, even though the non-english code makes it really difficult to understand what you are actually doing there...

What happens is: You have a Collection of something. Your Converter runs through that collection and calls getAsString() on each object. After you selected something in the browser, the value (return value of getAsString()) will be transmit to the converter and getAsObject() will be called. This is a completely NEW object and not necesssarily one of the collection from before (unless your Converter will actually access that collection and take it from there). After that JSF will take the collection it used to generate the selectOneMenu and compare every item with the one that the converter returned.

This might either happen by equals() or hashCode(), depending on what collection was used. So you need to override both at the same time (which you actually ALWAYS should do).

If JSF couldn't find any object from the collection that matches the one that the converter returned (equals is true, or the hashCode is the same) then you get Validation Error: Value is not valid.

I hope that cleared the process up a bit. My guess is that you either have to implement hashCode(), or that your equals() method is wrong. The setup in total is correct. You need to debug and check why exactly JSF fails to find the object in your list.

Share:
15,697

Related videos on Youtube

smiechu_skce
Author by

smiechu_skce

Updated on September 15, 2022

Comments

  • smiechu_skce
    smiechu_skce over 1 year

    I'm making a project in JSF with PrimeFaces and I have a problem with <p:SelectOneMenu>, specifically with a conversion of selected value from an object to String. I have written required Converter class, implemented toString() and equals() methods, as I think, quite correct. However, in a <h:messages /> component it endlessly gives me:

    j_idt7:j_idt92: Validation Error: Value is not valid
    j_idt7:j_idt98: Validation Error: Value is not valid

    I have to choose values which are part of the one bigger form. Then, based on the selected owner (właściciel) and company (firma), I add them to the database.

    This is my <p:SelectOneMenu> (twice - two menus):

    <p:selectOneMenu value="#{wniosek.selectedWl}" var="w">
    <f:selectItem itemLabel="Wybierz" itemValue=""/>
       <f:selectItems value="#{wniosek.listaWl}" var="wlasciciel" 
          itemLabel="#{wlasciciel.nazwisko}" itemValue="#{wlasciciel}" />
    
          <p:column>
              #{w.nazwisko}
          </p:column>
          <f:converter converterId="WlascicielConverter" />
    </p:selectOneMenu>                      
     <h:outputText value="Nazwa firmy: "/>
    
     <p:selectOneMenu value="#{wniosek.selectedFi}"  var="f">
          <f:selectItem itemLabel="Wybierz" itemValue=""/>
          <f:selectItems value="#{wniosek.listaFi}" var="firma" 
               itemLabel="#{firma.nazwa}" itemValue="#{firma}" />
          <f:converter converterId="FirmaConverter" />
          <p:column>
               #{f.nazwa}
          </p:column>
     </p:selectOneMenu>
    

    This is my Converter class for an owner's <p:SelectOneMenu>(similarly I've done with the company one):

    public class WlascicielConverter implements Converter {
    
    int i = 0;
    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
        try {           
            if (arg2 == null || arg2.isEmpty()) {
                return null;
            }
            String owner = arg2;
            return WlascicielBean.findAnOwner(owner);
    
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
    
        if(arg2 == null) return null;
    
        Wlasciciel owner = new Wlasciciel();
    
        if(arg2 instanceof Wlasciciel) {
            owner = (Wlasciciel)arg2;
            System.out.println(owner.getNazwisko());
            String surname = owner.getNazwisko();
            return (surname != null) ? String.valueOf(surname) : null;
        } else throw new ConverterException("Something wrong!" + arg2.hashCode() + arg2.toString());
    
    }
    

    }

    An equals() method:

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof Wlasciciel)) return false;
    
        Wlasciciel wl = (Wlasciciel)obj;
        if (this.id_w != wl.getId_w()) return false; 
        if (!this.nazwisko.equals(wl.getNazwisko())) return false; 
        if (!this.imie.equals(wl.getImie())) return false;      
        if (!this.ulica.equals(wl.getUlica())) return false; 
        if (this.nr != wl.getNr()) return false; 
        if (this.lokal != wl.getLokal()) return false; 
        if (this.id_n != wl.getId_n()) return false; 
    
        return true;
    }
    

    Could you give me some hints about solving this problem? I've read many tutorials about the converters in JSF, tried many ways to improve it, but it still doesn't work. I don't know... maybe the problem is somewhere else in my code? Because of its length I wouldn't paste it here (of course, if it's necessary, I'll do it).

  • BalusC
    BalusC over 10 years
    Another possible cause is that <f:selectItems value> list has changed during form submit. See also stackoverflow.com/questions/9069379/… Kudos for deciphering Polish code anyway :)
  • smiechu_skce
    smiechu_skce over 10 years
    I'm still fighting with this problem. I tried to examine why the converter works inproperly and I found, that the arg2 object in getAsString method is a String, not a Wlascicel object (but it should be, isn't it?). So I receive a ClassCastException - it can't convert String to Wlasciciel. I've editted the previous listing and inserted an up-to-date converter. I really don't know, what's wrong.