I found what I think is an anormal behaviour of the <p:autocomplete> component.
Server : Websphere AS 7.0.0.13
JSF : mojarra 2.0.3 (JSF 2.0)
Primefaces : 2.2-RC2
I use an autocomplete component with POJO support, my POJOs have a label and an id.
Code: Select all
<p:autoComplete
id="site"
value="#{myBean.selectedSite}"
required="true"
converter="#{myBean.siteConverter}"
completeMethod="#{myBean.completeSite}"
var="site"
itemLabel="#{site.label}"
itemValue="#{site}"
forceSelection="true"
minQueryLength="0"
widgetVar="siteAutoComplete"
onclick="siteAutoComplete.search(siteAutoComplete.value)"/>
Code: Select all
public class SiteConverter implements Converter, Serializable {
private static final long serialVersionUID = 1L;
private Collection<Site> cache;
public SiteConverter(final Collection<Site> cache) {
this.cache = cache;
}
@Override
public Object getAsObject(final FacesContext context, final UIComponent component,
final String value) {
if (value == null || value.trim().isEmpty()) {
return null;
}
Long siteId;
try {
siteId = Long.parseLong(value);
} catch (NumberFormatException e) {
String message = "Site convertion error with id=\"" + value + "\"";
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message,
null);
throw new ConverterException(facesMessage, e);
}
Site site = null;
if (cache != null) {
for (Site s : cache) {
if (s != null && s.getId() != null && s.getId().equals(siteId)) {
site = s;
break;
}
}
}
if (site == null) {
String message = "Site convertion error with id=\"" + value + "\"";
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null);
throw new ConverterException(facesMessage);
}
return site;
}
@Override
public String getAsString(final FacesContext context, final UIComponent component,
final Object value) {
if (value == null) {
return "";
}
if (!(value instanceof Site)) {
throw new IllegalArgumentException("Cannot convert non-Site object.");
}
Site site = (Site) value;
if (site.getId() == null) {
throw new IllegalArgumentException("Cannot convert Site object with null id.");
}
return Long.toString(site.getId());
}
}
On client side, two <input> tags are generated : site_input, this is what I type, and site_hinput, this is (should be) the id of the selected item.
When I select a site in the autocomplete list :
- site_input is set to the site label, and site_hinput is set to the site id--> OK
- an ajax POST is done to update the selected site on server-side --> OK
- the site_hinput field is processed by the SiteConverter, and a site corresponding to the id is found --> OK
Ajax POSTs (catched with firebug) :
Code: Select all
mainForm:site_hinput 2
mainForm:site_input FLA - Site de Flamanville
mainForm:site_query FLA - Site de Flamanville
- site_input contains "FLA", and site_hinput contains the same value --> why ?? No site has been selected, FLA does not correspond to a site_id. Why doesn't site_hinput contains a null value ??
- an ajax POST is done to update the selected site on server-side --> why ?? Again, no site has been selected. The "FLA" value is sent, which does not correspond to a site id. Let's say we consider I unselected the previous site, and selected an empty site instead by typing the "FLA" value : it is a null value that should be send to server, in order to put a null value as selected site.
- the site_hinput field is processed by the SiteConverter, and an error happen --> KO, my converter handles site ids, not site labels. Sending "FLA" throws a Converter Exception.
Ajax POSTs (catched with firebug) :
Code: Select all
mainForm:site_hinput F
mainForm:site_input F
mainForm:site_query F
Code: Select all
mainForm:site_hinput FL
mainForm:site_input FL
mainForm:site_query FL
Code: Select all
mainForm:site_hinput FLA
mainForm:site_input FLA
mainForm:site_query FLA
Code: Select all
2011-03-15 16:08:41,927 ERROR [ebContainer : 4 ] Exhaustive - Exception launched in Object fr.XXXXX.SiteConverter.getAsObject(FacesContext, UIComponent, String) with arguments [com.sun.faces.context.FacesContextImpl@63d963d9, org.primefaces.component.autocomplete.AutoComplete@39b839b8, F]
javax.faces.convert.ConverterException: Site convertion error with id=FLA.
at fr.XXXXX.SiteConverter.getAsObject(SiteConverter.java:133)
at org.primefaces.component.autocomplete.AutoCompleteRenderer.getConvertedValue(AutoCompleteRenderer.java:215)
at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1023)
at javax.faces.component.UIInput.validate(UIInput.java:953)
at javax.faces.component.UIInput.executeValidate(UIInput.java:1204)
at javax.faces.component.UIInput.processValidators(UIInput.java:693)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:469)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:175)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1476)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1487)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1487)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1487)
at javax.faces.component.UIForm.visitTree(UIForm.java:331)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1487)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1487)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:361)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:241)
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:179)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1157)
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:72)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
But if I want to handle this field on client-side with JavaScript, the strange behaviour of the site_hinput field is annoying. The convertion errors on server-side are annoying too.