EntityConverter and <s:convertEntity /> have serious limitation in both Seam 2.0 and 1.2.1.GA - they require entity to be Seam managed.
I've solved this by not using <s:convertEntity />. Instead I've created generic class EntitySelector which returns list of Ids and converter. I'd extend this class for each dropdown (you probably would want to have a backing bean for dropdown anyway). public abstract class EntitySelector<ID extends Serializable, ENTITY extends Serializable> implements Serializable { | | private final static Log log = LogFactory.getLog(EntitySelector.class); | | private static final int DEFAULT_SIZE = 0; | private EntitySelectorConverter<ID, ENTITY> converter; | | private Map<String, ENTITY> lookupMap = new HashMap<String, ENTITY>(DEFAULT_SIZE); | private List<ID> keyList = new ArrayList<ID>(DEFAULT_SIZE); | private List<ENTITY> values = new ArrayList<ENTITY>(DEFAULT_SIZE); | | public static Object getId(Object bean) { | Class<?> clazz = bean.getClass(); | log.trace("bean.getClass(): #0", clazz); | if (!clazz.isAnnotationPresent(javax.persistence.Entity.class)) { | // this better be instrumented proxy class | clazz = clazz.getSuperclass(); | log.trace("bean.getClass().getSuperclass(): #0", clazz); | } | return Entity.forClass(clazz).getIdentifier(bean); | } | | public ID getId(ENTITY bean) { | return (ID) EntitySelector.getId((Object) bean); | } | | public EntitySelector() { | converter = new EntitySelectorConverter<ID, ENTITY>(this); | } | | public void init(List<ENTITY> entities, Comparator<ENTITY> comparator) { | if (entities != null) { | values = entities; | if (comparator != null) { | Collections.sort(values, comparator); | } | final int size = values.size(); | lookupMap = new HashMap<String, ENTITY>(size); | keyList = new ArrayList<ID>(size); | for (ENTITY entity : entities) { | ID key = getId(entity); | String strKey = key.toString(); | lookupMap.put(strKey, entity); | keyList.add(key); | } | } | } | | @WebRemote | public Map<String, ENTITY> getLookupMap() { | return lookupMap; | } | | @WebRemote | public List<ID> getKeyList() { | return keyList; | } | | @WebRemote | public List<ENTITY> getValues() { | return values; | } | | @WebRemote | public ENTITY getByKey(String strKey) { | ENTITY entity = null; | if (lookupMap != null) { | entity = lookupMap.get(strKey); | } | return entity; | } | | public EntitySelectorConverter<ID, ENTITY> getConverter() { | return converter; | } | } public class EntitySelectorConverter<ID extends Serializable, ENTITY extends Serializable> | implements javax.faces.convert.Converter, Serializable { | | private final static Log log = LogFactory.getLog(EntitySelectorConverter.class); | | private EntitySelector<ID, ENTITY> entitySelector; | | public EntitySelectorConverter(EntitySelector<ID, ENTITY> selector) { | log.trace("EntitySelectorConverter selector=#0", selector); | entitySelector = selector; | } | | public String getAsString(FacesContext facesContext, UIComponent cmp, | Object entity) throws ConverterException { | if (entity == null) { | return null; | } | ID id = entitySelector.getId((ENTITY) entity); | log.trace("EntitySelectorConverter getAsString=#0 id=#1", entity, id); | return id.toString(); | } | | public Object getAsObject(FacesContext facesContext, UIComponent cmp, | String value) throws ConverterException { | ENTITY entity = entitySelector.getByKey(value); | log.trace("EntitySelectorConverter getAsObject=#0, entity=#1", value, entity); | return entity; | } | } This is how you would use it @Name("timeZones") | public class TimeZoneBean extends EntitySelector<String, TimeZone> { | | @Create | public void create() { | List<TimeZone> timeZones = ... | init(timeZones, null); | } | } And source tag: <ui:component xmlns="http://www.w3.org/1999/xhtml" | xmlns:s="http://jboss.com/products/seam/taglib" | xmlns:ui="http://java.sun.com/jsf/facelets" | xmlns:f="http://java.sun.com/jsf/core" | xmlns:a="https://ajax4jsf.dev.java.net/ajax" | xmlns:h="http://java.sun.com/jsf/html" | xmlns:w="http://facelets-tags.com/tags" | xmlns:rich="http://richfaces.ajax4jsf.org/rich"> | <h:selectOneMenu id="#{id}" styleClass="formtext" required="#{required}" value="#{value}" converter="#{timeZones.converter}" rendered="#{empty rendered ? true : rendered}"> | <s:selectItems value="#{timeZones.values}" var="timeZoneVar" noSelectionLabel="#{noSelectionLabel}" hideNoSelectionLabel="#{hideNoSelectionLabel}" | label="#{timeZoneVar.timeZoneId}" /> | </h:selectOneMenu> | </ui:component> Please, let me know what you think about this approach. Thanks View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4071208#4071208 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4071208 _______________________________________________ jboss-user mailing list jboss-user@lists.jboss.org https://lists.jboss.org/mailman/listinfo/jboss-user