coerceToType give strange side effects

From: Pieter Pareit <>
Date: Thu, 28 Jun 2007 11:48:20 +0000

Hi to all,I have strange things going on with the coerceToType in the SelectOneMenu.- Current value is not selected- I get errors like "value is not valid" (my selected value is not in the option list, but it is...)I'm using JSF1.2_04-b16-P02 (tomcat 6.0.13)Below a short review of what I do.A) Frist of all I have all my model beans extending a PersistentBean class.-------------------------------- class persistent beanpublic abstract class PersistentBean<T extends PersistentBean> implements Serializable { private long id; public long getId() { return id; } public void setId(long id) { = id; } public boolean equals(Object object) { if (this == object){ return true; } if ((object == null) || !(object instanceof PersistentBean)){ return false; } return ((PersistentBean) object).getId() == id; } public int hashCode() { return super.hashCode(); }}b) I have two model beans-------------------------------- class apublic class A extends PersistentBean<A>{ }-------------------------------- class bpublic class B extends A{ }c)I have a JSF managed bean with a value and list of SelectItem to construct my selectOneMenu (Note the different types)-------------------------------- Handler myJSFBeanpublic class MyJSFBean{ private B b; private ArrayList<SelectItem> options; // ----------------- init { b = new B(); b.setId(2); } // ----------------- GETTERS + SETTERS public B getB() { return b; } public void setB(B b) { this.b = b; } public ArrayList<SelectItem> getOptions() { if(options == null){ options = new ArrayList<SelectItem>(); A a = new A(); a.setId(1); A a2 = new A(); a2.setId(2); options.add(new SelectItem(a, "First value")); options.add(new SelectItem(a2, "Second value")); } return options; } public void setOptions(ArrayList<SelectItem> options) { this.options = options; }}d) I have some JSP code <h:selectOneMenu value="#{myJSFBean.b}" converter="pbConverter"> <f:selectItems value="#{myJSFBean.options}" /> </h:selectOneMenu>e) I have a converter to convert my PersistentBeans to a String value----------------------------------- pbConverterpublic class PersistentBeanConverter implements Converter, Serializable { public static final String CONVERTER_ID = "pbConverter"; private static final long serialVersionUID = 1; public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null || value.equals(StringUtils.EMPTY)) { return null; } long id; try { id = Long.parseLong(value); } catch (NumberFormatException e) { id = 0; e.printStackTrace(); } if (((UIInput) component).getValue() == null) { return createNewValue(context, component, id); } else { PersistentBean pk = (PersistentBean) ((UIInput) component) .getValue(); //To be sure the valueChangeListener is called if(pk.getId() != id){ return createNewValue(context, component, id); } return pk; } } private Object createNewValue(FacesContext context, UIComponent component, long id){ ValueExpression ve = component.getValueExpression("value"); try { PersistentBean pk = (PersistentBean) ve.getType(context.getELContext()) .newInstance(); pk.setId(id); return pk; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException( "pbConverer error could not instanciate the assignable object of the persistent bean", e); } } public String getAsString(FacesContext context, UIComponent component, Object value) { if (value == null || value.equals(StringUtils.EMPTY)) { return StringUtils.EMPTY; } if (value instanceof PersistentBean) { return String.valueOf(((PersistentBean) value).getId()); } else { throw new RuntimeException( "The pbConverter required a value of PersistentBean"); } }}-------------------------------------------------------Errors I get are:- Current value is not selected- I get errors like "value is not valid" (my selected value is not in the option list, but it is...)x this is because the type of my value and the type the value of my options are not the same.And note that i can't convert a A object in a B object !!!! --------------------------------------------------------I solved this by change the core JSF libraries--------------------- class javax.faces.component.UISelectOne starting at line 185 Class type = value.getClass(); Object newValue = getFacesContext().getApplication(). getExpressionFactory().coerceToType(item.getValue(), type); if (value.equals(newValue)) { return (true); } .......................... in if(value.equals(item.getValue())){ return (true); } The second class i changed is the--------------------- class com.sun.faces.renderkit.html_basic.MenuRenderer starting at line 580 Object newValue = context.getApplication().getExpressionFactory(). coerceToType(itemValue, type); isSelected = isSelected(newValue, valuesArray);.......................... inisSelected = isSelected(itemValue, valuesArray);Thanks in advance,Pieter Pareit
Play free games, earn tickets, get cool prizes! Join Live Search Club.