It seems like there should be a generic converter so that you can easily select the object from the drop down list without having to write a converter for every object type and without having to call the database (as most examples show). But there isn't that I know of, so I wrote my own converter to do this. Note that the converter expects the object to have a getId()
method which returns a unique ID of some kind. If it doesn't it will fail. You can add logic to the getMethodName()
if you need to determine the name of the method to use as a key programmatically. Note that we use Seam in our project. If you don't use Seam, the NO_SELECTION_VALUE parts can probably be removed as well as the three annotations on the class.
This code was inspired by: http://arjan-tijms.omnifaces.org/2011/12/automatic-to-object-conversion-in-jsf.html
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
import javax.faces.model.SelectItem;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.faces.Converter;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
/**
* @author: Jason Wheeler
* @description Converter for lists (SelectOneMenu, SelectManyMenu, etc)
* @created: 09/05/2013
*/
@Name("listConverter")
@BypassInterceptors
@Converter
public class ListConverter implements javax.faces.convert.Converter {
private String NO_SELECTION_VALUE = "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue";
@Override
public String getAsString(FacesContext facesContext, UIComponent component, Object obj) {
if (obj == null) {
return NO_SELECTION_VALUE;
} else {
try {
Method method = obj.getClass().getMethod(getMethodName(obj));
return String.valueOf(method.invoke(obj));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public String getMethodName(Object obj) {
return "getId";
}
@Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String val) throws ConverterException {
if (val == null) {
return null;
} else if (val.equals(NO_SELECTION_VALUE)) {
return null;
} else {
for (SelectItem item : getSelectItems(component)) {
if (val.equals(getAsString(facesContext, component, item.getValue()))) {
return item.getValue();
}
}
return null;
}
}
protected Collection<SelectItem> getSelectItems(UIComponent component) {
Collection<SelectItem> collection = new ArrayList<SelectItem>();
for (UIComponent child : component.getChildren()) {
if (child instanceof UISelectItem) {
UISelectItem ui = (UISelectItem) child;
SelectItem item = (SelectItem) ui.getValue();
collection.add(item);
} else if (child instanceof UISelectItems) {
UISelectItems ui = (UISelectItems) child;
Object value = ui.getValue();
collection.addAll((Collection<SelectItem>) value);
}
}
return collection;
}
}