2010-09-22 69 views
2

使用NetBeans,我生成了Hibernate映射文件和一组POJO。我还从实体类(生成的POJO)生成了一组JSF页面。JSF生成的页面和实体selectOneMenu

现在,我试图添加一个下拉菜单,使我能够选择其中一个参与者。

<h:selectOneMenu value="#{measurementController.sensor}"> 
    <f:selectItems value="#{sensorController.itemsAvailableSelectOne}" /> 
</h:selectOneMenu> 

getItemsAvailableSelectOne()调用此方法:

public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) { 
    int size = selectOne ? entities.size() + 1 : entities.size(); 
    SelectItem[] items = new SelectItem[size]; 
    int i = 0; 
    if (selectOne) { 
     items[0] = new SelectItem("", "---"); 
     i++; 
    } 
    for (Object x : entities) { 
     items[i++] = new SelectItem(x, x.toString()); 
    } 
    return items; 
} 

在measurementController类我有这样的:

private Sensor sensor; 

public Sensor getSensor() { 
    return this.sensor; 
} 

public void setSensor(Sensor sensor) { 
    this.sensor = sensor; 
} 

无论我做什么,我得到Validation Error: Value is not valid错误,当我选择的任何条目下拉式菜单。为什么?

我有一种感觉,我失去了一些非常明显的东西,但我无法看到它。

编辑:

挖掘低谷生成的代码,我发现一个现有的转换器类:

@FacesConverter(forClass=Sensor.class) 
public static class SensorControllerConverter implements Converter { 

    public Object getAsObject(FacesContext facesContext, UIComponent component, String value) { 
     if (value == null || value.length() == 0) { 
      return null; 
     } 
     SensorController controller = (SensorController)facesContext.getApplication().getELResolver(). 
       getValue(facesContext.getELContext(), null, "sensorController"); 
     return controller.ejbFacade.find(getKey(value)); 
    } 

    java.lang.Integer getKey(String value) { 
     java.lang.Integer key; 
     key = Integer.valueOf(value); 
     return key; 
    } 

    String getStringKey(java.lang.Integer value) { 
     StringBuffer sb = new StringBuffer(); 
     sb.append(value); 
     return sb.toString(); 
    } 

    public String getAsString(FacesContext facesContext, UIComponent component, Object object) { 
     if (object == null) { 
      return null; 
     } 
     if (object instanceof Sensor) { 
      Sensor o = (Sensor) object; 
      return getStringKey(o.getIdSensor()); 
     } else { 
      throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: "+SensorController.class.getName()); 
     } 
    } 

} 

当我踏上槽这一切似乎做工精细的调试器的代码。首先调用getAsObject方法,将所选项目作为参数,返回值为Sensor对象。

然后调用返回null(存储在measurementController类中的当前值)的getSensor()方法。

最后,调用下拉菜单中的每个项目的getAsString()方法。我认为这是渲染响应阶段的一部分,与验证无关。

回答

2

Validation Error: Value is not valid

<h:selectOneMenu>的情况下,你可以得到,只要所选择的项目不匹配任何在列表中每Object#equals()合同提供的项目该验证错误。基本上,归结起来,sensor.equals(selectItem.getValue())从未返回true列表中的任何SelectItem项目。如果Sensor类的equals()方法没有实施或执行不力,就会发生这种情况。

+0

我不敢相信我已经浪费了三天的时间了!我怎么能这么愚蠢。我没有实现equals方法。更糟糕的是 - 在我看来,验证器必须比较两个Sensor实例,并且我实现了equals方法 - 通过引用而不是按值比较Integer。感谢一堆提示。 – skajfes 2010-09-23 20:24:23

+0

不客气。你可以在[这个答案]中找到一些提示(http://stackoverflow.com/questions/3181339/right-way-to-implement-equals-contract/3181374#3181374)。 – BalusC 2010-09-23 20:34:17

1

您需要定义一个转换器将对象Sensor转换为String,反之亦然。

此转换器将通过JSF用来转换SensorString时,页面将呈现,并且它也将被用于从String转换为Sensor当值将在measurementController豆来设置,并在JSF组件树结构。


首先,定义一个转换器,它将实现 javax.faces.convert.Converter接口。在这个类中,定义两个方法 getAsObject()getAsString()。它们用于进行转换。

然后,在faces-config.xml文件中注册该转换器:

<converter> 
    <converter-id>SensorConverter</converter-id> 
    <converter-class>my.application.SensorConverter</converter-class>  
</converter> 

最后,你还可以定义为一个特定的类的自动转换器(在这种情况下,将不再需要最后一步):

<converter> 
    <converter-for-class>foo.bar.Sensor</converter-for-class> 
    <converter-class>my.application.SensorConverter</converter-class> 
</converter> 

最后,在您的<h:selectOneMenu/>组件中使用<f:converter id="SensorConverter"/>converterId="SensorConverter"

有关转换和验证的更多信息,请参阅here

+0

感谢您的快速响应。尽管如此,我只有一个问题。挖槽生成的代码我发现它已经存在一个用于传感器的Converter类,但它不起作用。我将使用代码编辑问题.... – skajfes 2010-09-23 05:20:18

+0

注册转换器的JSF 2.0方法使用'@ FacesConverter'注释。顺便说一下,如果没有合适的转换器,那么在验证发生之前,OP宁可得到一个转换错误,如'转换错误设置值[email protected]'为'null Converter'。 – BalusC 2010-09-23 20:43:20