0

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

<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是一个映射,其中对象的名称字段(即字符串)作为键,对象本身作为值。然后,默认选择 ( ) 的也是一个字符串,正如您在模型的 getter/setter 方法中看到的那样。value="#{detailModel.selectedBootenvironment1}"

另一个问题(可能与前一个有关)是,当页面第一次加载时,默认选择的值应该是 --Please select one--- 因为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

4

1 回答 1

2

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

实际上,您有一个Bootenvironment项目值列表,但您已将该属性绑定到 a String,这表明您依赖Bootenvironment#toString()作为提交值传递的值,并且您根本没有使用普通的 JSF Converter。AString永远不能返回一个对象trueequals()测试。Bootenvironment

您需要提供一个Converterwhich 在Bootenvironment及其唯一String表示之间进行转换。通常,使用技术 ID(例如从数据库中自动生成的 PK)作为唯一String表示。

@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属性修复为普通属性,而不会在 getter/setter 中出现任何混乱:

private Bootenvironment selectedBootenvironment1;

public Bootenvironment getSelectedBootenvironment1() {
    return selectedBootenvironment1;
}

public void setSelectedBootenvironment1(Bootenvironment selectedBootenvironment1) {
    this.selectedBootenvironment1 = selectedBootenvironment1;
}
于 2012-10-30T16:32:21.227 回答