Problem with JSF to SelectOneMenu converter

I have problems again. I want to say the following: In my project, I need a converter to (obviously) convert elements from the SelectOneMenu component to a list property in the corresponding bean. On my jsf page, I have:

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

And my bean:

 @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 ? } }; } ... } 

In the getAsObject () method, the value parameter is represented by the value that I passed to the SelectItem constructor. But in the getAsString () method, the value also appears as a string representation of Id. Should this parameter not be of type TdPublicType? Is there something wrong in my code?

+4
source share
3 answers

getAsString() should convert the Object (which is in your case of type TdPublicType ) to String , which uniquely identifies the instance, for example. some identifier so that it can be embedded in the HTML code and passed as parameters of the HTTP request. getAsObject() must convert this unique String representation back to a specific Object instance so that the passed HTTP request parameter can be converted back to the original object instance.

Basically (trivial preliminary quotes and exception handling are omitted):

 @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)); } 

Refresh . You have another problem: you specify the value property of the TdPublicType class as the value of the element instead of the TdPublicType instance TdPublicType . Thus, the converter will get the value property instead of the TdPublicType instance in getAsString() . Correct it accordingly:

 <f:selectItems value="#{publicoBean.lstPublicTypes}" var="pt" itemLabel="#{pt.label}" itemValue="#{pt}"/> 
+4
source

Now the code is working. My mistake was in the boot method. I did it:

 // 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())); } 

But the right way:

 // 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. } 
0
source

use can use a generic converter that converts the value to a backup bean. You also do not need casting.

 @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; } } 

Usage example will be

 <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> 
0
source

All Articles