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