jsf - Conversion Error setting value for 'null Converter' -
i have problems understanding how use selection in jsf 2 pojo/entity effectively. example, i'm trying select warehouse
entity via below dropdown:
<h:selectonemenu value="#{bean.selectedwarehouse}"> <f:selectitem itemlabel="choose 1 .." itemvalue="#{null}" /> <f:selectitems value="#{bean.availablewarehouses}" /> </h:selectonemenu>
and below managed bean:
@named @viewscoped public class bean { private warehouse selectedwarehouse; private list<selectitem> availablewarehouses; // ... @postconstruct public void init() { // ... availablewarehouses = new arraylist<>(); (warehouse warehouse : warehouseservice.listall()) { availablewarehouses.add(new selectitem(warehouse, warehouse.getname())); } } // ... }
notice use whole warehouse
entity value of selectitem
.
when submit form, fails following faces message:
conversion error setting value 'com.example.warehouse@cafebabe' 'null converter'.
i hoping jsf set correct warehouse
object managed bean when wrap in selectitem
. wrapping entity inside selectitem
meant skip creating converter
entity.
do have use converter
whenever want make use of entities in <h:selectonemenu>
? should jsf possible extract selected item list of available items. if have use converter, practical way of doing it? far came this:
- create
converter
implementation entity. - overriding
getasstring()
. think don't need since label property ofselectitem
used display dropdown option label. - overriding
getasobject()
. think used return correctselectitem
or entity depending on type of selected field defined in managed bean.
the getasobject()
confuses me. efficient way this? having string value, how associated entity object? should query entity object service object based on string value , return entity? or perhaps somehow can access list of entities form selection items, loop them find correct entity, , return entity?
what normal approach of this?
introduction
jsf generates html. html in java terms 1 large string
. represent java objects in html, have converted string
. also, when html form submitted, submitted values treated string
in http request parameters. under covers, jsf extracts them httpservletrequest#getparameter()
returns string
.
to convert between non-standard java object (i.e. not string
, number
or boolean
el has builtin conversions, or date
jsf provides builtin <f:convertdatetime>
tag), have supply custom converter
. selectitem
has no special purpose @ all. it's leftover jsf 1.x when wasn't possible supply e.g. list<warehouse>
directly <f:selectitems>
. has no special treatment labels , conversion.
getasstring()
you need implement getasstring()
method in such way desired java object been represented in unique string
representation can used http request parameter. normally, technical id (the database primary key) used here.
public string getasstring(facescontext context, uicomponent component, object modelvalue) { if (modelvalue == null) { return ""; } if (modelvalue instanceof warehouse) { return string.valueof(((warehouse) modelvalue).getid()); } else { throw new converterexception(new facesmessage(modelvalue + " not valid warehouse")); } }
note returning empty string in case of null/empty model value significant , required javadoc. see using "please select" f:selectitem null/empty value inside p:selectonemenu.
getasobject()
you need implement getasobject()
in such way exactly string
representation returned getasstring()
can converted exactly same java object specified modelvalue
in getasstring()
.
public object getasobject(facescontext context, uicomponent component, string submittedvalue) { if (submittedvalue == null || submittedvalue.isempty()) { return null; } try { return warehouseservice.find(long.valueof(submittedvalue)); } catch (numberformatexception e) { throw new converterexception(new facesmessage(submittedvalue + " not valid warehouse id"), e); } }
in other words, must technically able pass returned object modelvalue
argument of getasstring()
, pass obtained string submittedvalue
argument of getasobject()
in infinite loop.
usage
finally annotate converter
@facesconverter
hook on object type in question, jsf automatically take care of conversion when warehouse
type ever comes picture:
@facesconverter(forclass=warehouse.class)
that "canonical" jsf approach. it's after not effective indeed have grabbed item <f:selectitems>
. important point of converter
returns unique string
representation, java object identified simple string
suitable passing around in http , html.
generic converter based on tostring()
jsf utility library omnifaces has selectitemsconverter
works based on tostring()
outcome of entity. way not need fiddle getasobject()
, expensive business/database operations anymore. concrete use examples, see showcase.
to use it, register below:
<h:selectonemenu ... converter="omnifaces.selectitemsconverter">
and make sure tostring()
of warehouse
entity returns unique representation of entity. instance directly return id:
@override public string tostring() { return string.valueof(id); }
or more readable/reusable:
@override public string tostring() { return "warehouse[id=" + id + "]"; }
see also:
- how populate options of h:selectonemenu database?
- generic jsf entity converter - don't need write converter every entity.
- using enums in jsf selectitems - enums needs treated bit differently
- how inject @ejb, @persistencecontext, @inject, @autowired, etc in @facesconverter?
unrelated problem, since jsf 2.0 it's not explicitly required anymore have list<selectitem>
<f:selectitem>
value. list<warehouse>
suffice.
<h:selectonemenu value="#{bean.selectedwarehouse}"> <f:selectitem itemlabel="choose 1 .." itemvalue="#{null}" /> <f:selectitems value="#{bean.availablewarehouses}" var="warehouse" itemlabel="#{warehouse.name}" itemvalue="#{warehouse}" /> </h:selectonemenu>
private warehouse selectedwarehouse; private list<warehouse> availablewarehouses;
Comments
Post a Comment