Converter in JSF (PrimeFaces) with SelectOneMenu: Validation Error
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.
Related videos on Youtube
smiechu_skce
Updated on September 15, 2022Comments
-
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, implementedtoString()
andequals()
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 over 10 yearsAnother 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 over 10 yearsI'm still fighting with this problem. I tried to examine why the converter works inproperly and I found, that the
arg2
object ingetAsString
method is aString
, not aWlascicel
object (but it should be, isn't it?). So I receive aClassCastException
- it can't convertString
toWlasciciel
. I've editted the previous listing and inserted an up-to-date converter. I really don't know, what's wrong.