3 Replies Latest reply on Sep 8, 2011 5:23 AM by hantsy

    EntityConverter in Seam 3...

    hantsy

      There 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



        • 1. Re: EntityConverter in Seam 3...
          nickarls

          Tried what entityManager.getEntityManagerFactory().getPersistenceUnitUtil.getIdentifier() returns? In other cases you'll just have to walk up the inheritance hierarchy until you find the ID, I guess.

          • 2. Re: EntityConverter in Seam 3...
            hantsy

            Thanks

            • 3. Re: EntityConverter in Seam 3...
              hantsy
              @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));
                   }
              



              entityType alwasy return a Object instead of a Entity class.