JSF生成的页面和实体,selectOneMenu

时间:2010-09-22 21:01:50

标签: java jsf jsf-2

使用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响应阶段的一部分,与验证无关。

2 个答案:

答案 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