我在页面中定义了以下下拉框: ...
<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
答案 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}}