我又遇到麻烦了。我的观点是:在我的项目中,我需要一个转换器,用于(显然)将SelectOneMenu组件中的项转换为相应bean中的列表属性。在我的jsf页面中,我有:
<p:selectOneMenu id="ddlPublicType" value="#{publicBean.selectedPublicType}" effect="fade" converter="#{publicBean.conversor}" >
<f:selectItems value="#{publicoBean.lstPublicTypes}" var="pt" itemLabel="#{pt.label}" itemValue="#{pt.value}"></f:selectItems>
</p:selectOneMenu>
我的豆子是:
@ManagedBean(name = "publicBean")
@RequestScoped
public class PublicBean {
// Campos
private String name; // Nome do evento
private TdPublicType selectedPublicType = null;
private List<SelectItem> lstPublicTypes = null;
private static PublicTypeDAO publicTypeDao; // DAO
static {
publicTypeDao = new PublicTypeDAO();
}
// Construtor
public PublicoBean() {
lstPublicTypes = new ArrayList<SelectItem>();
List<TdPublicType> lst = publicTypeDao.consultarTodos();
ListIterator<TdPublicType> i = lst.listIterator();
lst.add(new SelectItem("-1","Select..."));
while (i.hasNext()) {
TdPublicType actual = (TdPublicType) i.next();
lstPublicTypes.add(new SelectItem(actual.getIdPublicType(), actual.getNamePublicType()));
}
}
// Getters e Setters
...
public Converter getConversor() {
return new Converter() {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// This value parameter seems to be the value i had passed into SelectItem constructor
TdPublicType publicType = null; // Retrieving the PublicType from Database based on ID in value parameter
try {
if (value.compareTo("-1") == 0 || value == null) {
return null;
}
publicType = publicTypeDao.findById(Integer.parseInt(value));
} catch (Exception e) {
FacesMessage msg = new FacesMessage("Error in data conversion.");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext.getCurrentInstance().addMessage("info", msg);
}
return publicType;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return value.toString(); // The value parameter is a TdPublicType object ?
}
};
}
...
}
在getAsObject()方法中,value参数似乎是我传递给SelectItem构造函数的值。但是在getAsString()方法中,该值似乎也是Id的字符串表示。该参数的类型不应该是TdPublicType?我的代码有什么错误吗?
getAsString()
应该将Object
(在类型为TdPublicType
的情况下)转换为唯一标识实例(例如某个ID)的String
,以便将其内联在HTML代码中并作为HTTP请求参数传递。getAsObject()
应该将唯一的String
表示转换回具体的Object
实例,这样提交的HTTP请求参数就可以转换回原始对象实例。
基本上(省略了琐碎的预检查和异常处理):
@Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) throws ConverterException {
// Convert Object to unique String representation for display.
return String.valueOf(((TdPublicType) modelValue).getId());
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) throws ConverterException {
// Convert submitted unique String representation back to Object.
return tdPublicTypeService.find(Long.valueOf(submittedValue));
}
更新:您遇到了另一个问题,您将TdPublicType
类的value
属性指定为项值,而不是TdPublicType
实例本身。这样,转换器将检索value
属性,而不是getAsString()
中的TdPublicType
实例。相应地修复:
<f:selectItems value="#{publicoBean.lstPublicTypes}" var="pt"
itemLabel="#{pt.label}" itemValue="#{pt}"/>
现在代码开始工作了。我的错误在于加载方法。我在做这个:
// Loading menu
List<TdPublicType> l = daoPublicType.retrieveAll();
Iterator<TdPublicType> i = l.iterator();
while (i.hasNext()) {
TdPublicType actual = (TdPublicType) i.next();
lstMenuPublicType.add(new SelectItem(actual.getIdtPublicType(), actual.getNamePublicType()));
}
但正确的方法是:
// Loading menu
List<TdPublicType> l = daoPublicType.retrieveAll();
Iterator<TdPublicType> i = l.iterator();
while (i.hasNext()) {
TdPublicType actual = (TdPublicType) i.next();
lstMenuPublicType.add(new SelectItem(actual, actual.getNamePublicType())); // In the first parameter i passed the PublicType object itself not his id.
}
use可以使用通用转换器,它将转换backingbean中的值。你也不需要任何铸造。
@FacesConverter(value = "GConverter")
public class GConverter implements Converter{
private static Map<Object, String> entities = new WeakHashMap<Object, String>();
@Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
synchronized (entities) {
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
}
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
for (Entry<Object, String> entry : entities.entrySet()) {
if (entry.getValue().equals(uuid)) {
return entry.getKey();
}
}
return null;
}
}
示例用法为
<p:selectOneMenu id="ddlPublicType" value="#{publicBean.selectedPublicType}" effect="fade" converter="GConverter" >
<f:selectItems value="#{publicoBean.lstPublicTypes}" var="pt" itemLabel="#{pt.label}" itemValue="#{pt}"></f:selectItems>
</p:selectOneMenu>