h:selectOneMenu:验证错误

时间:2012-10-30 14:46:36

标签: java jsf-2

我在页面中定义了以下下拉框:     ...

<td>
  <h:selectOneMenu id="bootenvironment1" value="#{detailModel.selectedBootenvironment1}"
                   disabled="#{detailModel.mode == detailModel.viewMode}">
    <f:selectItems value="#{detailModel.availableBootenvironments}"/>
  </h:selectOneMenu>
</td>

在我的模特中,我有:

...
  private Map<String, Bootenvironment> availableBootenvironments;

  public DefinitionDetailModel()
  {
    super();
  }

  public String getSelectedBootenvironment1()
  {
    if (((Definition) getAfterObject()).getBootenvironment1() != null)
    {
      return ((Definition) getAfterObject()).getBootenvironment1().getEnvironmentName();
    }

    return "--Please select one--";
  }

  public void setSelectedBootenvironment1( String selectedBootenvironment )
  {
    ((Definition) getAfterObject()).setBootenvironment1(availableBootenvironments.get(selectedBootenvironment));
  }
  ...

在控制器中我设置了availableBootenvironments地图:

private void fetchBootenvironments()
  {
    ...
    @SuppressWarnings( "unchecked" )
    List<Bootenvironment> bootenvironments = (List<Bootenvironment>) ...

    Map<String, Bootenvironment> availableBootenvironments = new HashMap<String, Bootenvironment>();

    availableBootenvironments.put("--Please select one--", null);

    for(Bootenvironment bootenvironment : bootenvironments)
    {
      availableBootenvironments.put(bootenvironment.getEnvironmentName(), bootenvironment);
    }

    ((DefinitionDetailModel) detailModel).setAvailableBootenvironments(availableBootenvironments);
  }

问题是当我点击页面中的一个按钮(绑定到一个动作)时,我收到错误:

  

detailForm:bootenvironment1:验证错误:值无效。

我不明白错误在哪里; selectItems 是一个地图,其中对象的名称字段(字符串)作为键,对象本身作为值。然后,默认选中的{em>值(value="#{detailModel.selectedBootenvironment1}")也是一个字符串,您可以在模型的getter / setter方法中看到。

另一个问题(可能与前一个问题有关)是当页面首次加载时,默认选择的值应为 - 请选择一个---因为 getBootenvironment1()返回 null ,但这不会发生:选择列表中的另一个。

你能帮我理解我做错了什么/我在哪里?

修改

我按照你说的那样实现了转换器:

@FacesConverter( forClass = Bootenvironment.class )
public class BootenvironmentConverter implements Converter
{

  @Override
  public String getAsString( FacesContext context, UIComponent component, Object modelValue ) throws ConverterException
  {
    return String.valueOf(((Bootenvironment) modelValue).getDbId());
  }

  @Override
  public Object getAsObject( FacesContext context, UIComponent component, String submittedValue ) throws ConverterException
  {
    List<Bootenvironment> bootenvironments = ... (get from DB where dbid=submittedValue)

    return bootenvironments.get(0);
  }

}

但现在我有以下错误:

  

java.lang.ClassCastException:java.lang.String无法强制转换为   ch.ethz.id.wai.bootrobot.bo.Bootenvironment

1 个答案:

答案 0 :(得分:2)

当所选项目值未通过任何可用项目值的equals()测试时,您将收到此错误。

事实上,您有一个Bootenvironment项值列表,但您已将该属性绑定到String,表示您依赖Bootenvironment#toString()值作为提交的值传递,并且您根本没有使用普通的JSF Converter。使用String对象的true测试中,equals()永远无法返回Bootenvironment

您需要提供Converter,该Bootenvironment可在String及其唯一String表示之间进行转换。通常,技术ID(例如来自数据库的自动生成的PK)被用作唯一的@FacesConverter(forClass=Bootenvironment.class) public class BootenvironmentConverter implements Converter { @Override public void getAsString(FacesContext context, UIComponent component, Object modelValue) throws ConverterException { // Write code to convert Bootenvironment to its unique String representation. E.g. return String.valueOf(((Bootenvironment) modelValue).getId()); } @Override public void getAsObject(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException { // Write code to convert unique String representation of Bootenvironment to concrete Bootenvironment. E.g. return someBootenvironmentService.find(Long.valueOf(submittedValue)); } } 表示。

selectedBootenvironment1

最后,在相应地实现转换器之后,您应该能够将private Bootenvironment selectedBootenvironment1; public Bootenvironment getSelectedBootenvironment1() { return selectedBootenvironment1; } public void setSelectedBootenvironment1(Bootenvironment selectedBootenvironment1) { this.selectedBootenvironment1 = selectedBootenvironment1; } 属性修复为普通属性,而不会在getter / setter中出现任何混乱:

{{1}}