使用NetBeans,我生成了Hibernate映射文件和一组POJO。我还从实体类(那些生成的POJO)生成了一组JSF页面。
现在,我正在尝试添加一个下拉菜单,以便我选择其中一个功能。
<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对象。
然后调用getSensor()方法返回null(存储在measurementController类中的当前值)。
最后,为下拉菜单中的每个项调用getAsString()方法。我认为这是Render响应阶段的一部分,与验证无关。
答案 0 :(得分:2)
验证错误:值无效
如果是<h:selectOneMenu>
,只要所选项目与Object#equals()
合同中列表中的任何可用项目不匹配,您就会收到此验证错误。基本上,归结为sensor.equals(selectItem.getValue())
从未返回true
列表中可用的任何SelectItem
项目。如果equals()
类的Sensor
方法没有实现或执行不当,就会发生这种情况。
答案 1 :(得分:1)
您需要定义转换器以将对象Sensor
转换为String
,反之亦然。
当呈现页面时,JSF将使用此转换器将Sensor
转换为String
,并且它还将用于从String
转换为Sensor
当值将在measurementController
bean和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>
最后,使用<f:converter id="SensorConverter"/>
组件中的converterId="SensorConverter"
或<h:selectOneMenu/>
。
有关转化和验证的更多信息,请参见here。