[jboss-user] [JBoss Seam] - Re: EntityConverter: Entity Manager not found

mgrouch do-not-reply at jboss.com
Mon Aug 6 10:27:47 EDT 2007


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



More information about the jboss-user mailing list