EntityConverter in Seam 3...
hantsy Sep 2, 2011 7:53 AMThere is no entityConverter in Seam3...
I searched via Google and get the following version...
public class EntityConverter implements javax.faces.convert.Converter, PartialStateHolder { private static final Object[] ZERO_ARGS = new Object[] {}; @PersistenceContext private EntityManager entityManager; private Map<String, Serializable> stateMap = new ConcurrentHashMap<String, Serializable>(); private boolean initialStateMarked; private boolean isTransient; @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { final ValueExpression ve = component.getValueExpression("value"); final Class<?> entityType = ve.getExpectedType(); return this.entityManager.find(entityType, this.stateMap.get(value)); } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { final Serializable id = this.findId(value); final String idKey = value.getClass().getSimpleName() + id.hashCode(); if (!this.stateMap.containsKey(idKey)) { this.stateMap.put(value.getClass().getSimpleName() + id.hashCode(), id); } return idKey; } private Serializable findId(Object entity) { final EntityType<?> entityType = this.entityManager.getMetamodel() .entity(entity.getClass()); final Member idAttribute = entityType.getId(entity.getClass()) .getJavaMember(); Property p = Properties.createProperty(idAttribute); return (Serializable) p.getValue(entity); } // ---------- State saving -------------- @Override public void markInitialState() { this.initialStateMarked = true; } @Override public boolean initialStateMarked() { return this.initialStateMarked; } @Override public void clearInitialState() { this.stateMap = new ConcurrentHashMap<String, Serializable>(); this.initialStateMarked = false; } @Override public Object saveState(FacesContext context) { if (context == null) { throw new IllegalArgumentException("FacesContext must not be null"); } return Collections.unmodifiableMap(this.stateMap); } @Override public void restoreState(FacesContext context, Object state) { if (state != null) { this.stateMap = new ConcurrentHashMap<String, Serializable>( (Map<? extends String, ? extends Serializable>) state); return; } this.stateMap.clear(); } @Override public boolean isTransient() { return this.isTransient; } @Override public void setTransient(boolean newTransientValue) { this.isTransient = newTransientValue; } }
What I applied in my application, I got an exception.
java.lang.IllegalArgumentException: Id attribute was not of specified type : com.telopsys.siorc.model.Country at org.hibernate.ejb.metamodel.AbstractIdentifiableType.getId(AbstractIdentifiableType.java:95) at org.hibernate.ejb.metamodel.AbstractIdentifiableType.getId(AbstractIdentifiableType.java:110) at com.telopsys.siorc.converter.EntityConverter.findId(EntityConverter.java:59) at com.telopsys.siorc.converter.EntityConverter.getAsString(EntityConverter.java:45) at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:519) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOption(MenuRenderer.java:534) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderOptions(MenuRenderer.java:792) at com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:844) at com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:298) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883) at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312) at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652) at com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:78) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652) at javax.faces.render.Renderer.encodeChildren(Renderer.java:168) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652) at org.richfaces.renderkit.RendererBase.renderChildren(RendererBase.java:278) at org.richfaces.renderkit.html.PopupPanelRenderer.encodeEnd(PopupPanelRenderer.java:534) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883)
It can not find the id attribute in my entity object, the Country is extended a base class BaseEntity which declared the id property.
By the way, the original version of the codes used @Inject @Any on the EntityManager, I think it works in a servlet runtime environment, I am using Seam 3 on Jboss 7 currently, so I must use @PersistenceContext to inject entityManger, is there a generic way to inject entityManager?
Regards