1 2 Previous Next 16 Replies Latest reply on Aug 7, 2007 6:18 PM by mgrouch

    EntityConverter: Entity Manager not found

    Jens Weintraut Apprentice

      Hi there,

      I've encountered a strange behavior in my application. There are several s:selectItems on a page using s:convertEntity to display dropdown-boxes filled with entities.

      <ice:selectOneMenu value="#{userSelector.selectedUser}" partialSubmit="true">
       <s:selectItems value="#{userSelector.users}" var="user" label="#{user.ID} - #{user.name}" noSelectionLabel="#{ares_messages.filter_all}" />
       <s:convertEntity />
      </ice:selectOneMenu>


      When the page is rendered the first time, the dropdowns are rendered as they should be. So I think everything is fine with the EntityManager.

      Below the dropdowns there's a dataTable. The dataTable shows some information according to the selected items in those drop-downs. With a commandLink you can select an entry to display further information.

      <h:column>
       <f:facet name="header">
       <ice:commandSortHeader columnName="id">
       <h:outputText value="#{ares_messages.label_testaction_ID}" />
       </ice:commandSortHeader>
       </f:facet>
       <ice:commandLink value="#{testaction_var.ID}" action="#{testactionDeveloper.select(testaction_var)}" />
      </h:column>


      As you can see I use Seam's EL enhancement to let the backing bean know which item was clicked.

      OK. Let's remember that the page was displayed normally. Now I click on a commandLink to display further information resulting in a message "Error selecting object" in the h:message tag. The console tells me that "ERROR [EntityConverter] Entity Manager not found".
      But why? The EntityConverter has already converted the entities from the database. Why isn't it possible to select an item in the datatable?

      Thanks in advance
      Newlukai

        • 2. Re: EntityConverter: Entity Manager not found
          Jens Weintraut Apprentice

          Seam 1.2.1.GA
          ICEfaces 1.6.0
          JBoss AS 4.0.5.GA

          • 3. Re: EntityConverter: Entity Manager not found
            Pete Muir Master

            Please try using Seam2

            • 4. Re: EntityConverter: Entity Manager not found
              Jens Weintraut Apprentice

              Hmm. OK. I don't want to try it since it's still beta, but I'll do it next week. Do you have an idea what it could be?

              • 5. Re: EntityConverter: Entity Manager not found
                Pete Muir Master

                No, the reason to upgrade is I completely redid the way entity converter works for seam 2

                • 6. Re: EntityConverter: Entity Manager not found
                  Jens Weintraut Apprentice

                  Hehe. OK. I'll test it.

                  • 7. Re: EntityConverter: Entity Manager not found
                    Jens Weintraut Apprentice

                    I tried it. I really did. But I had to surrender facing the list of things to do to migrate to Seam 2.0. Sorry.

                    So I'm on 1.2.1.GA again. The only major change before this mibehaviour occured was to introduce a @Startup component which is injected to the backing bean. But I don't know why this should produce an error in the EntityConverter when the page is submitted after it was successfully rendered.

                    • 8. Re: EntityConverter: Entity Manager not found
                      mgrouch Expert

                      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

                      • 9. Re: EntityConverter: Entity Manager not found
                        Pete Muir Master

                         

                        "mgrouch" wrote:
                        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 hardly think this is a "serious limitation" - you are using Seam after all, and you'd be silly not to use a SMPC with Seam.

                        Anyway, the main problem with this is that you cache every entity in the conversation scope (otherwise the entities become unmanaged) which is not too nice.

                        • 10. Re: EntityConverter: Entity Manager not found
                          mgrouch Expert

                          I think my code is better what Seam offers.
                          Scope is whatever you choose to be on a subclass of EntitySelector.
                          You are not restricted by requirement to use SMPC.
                          What if your entity list is coming from stateless session EJB call with no SMPC? My code would work. Seam would give you "Entity Manager not found" exception...

                          • 11. Re: EntityConverter: Entity Manager not found
                            Jens Weintraut Apprentice

                            Is it just since 1.2.1.GA that the entity has to be Seam managed? It could be an explanation for my problem. Fortunately since I tried to update to Seam 2 and then went back to 1.2.1 the problem has gone. But I'm still interested in recovering the reason.

                            Therefore could you please tell me what steps are necessary to assure that those entities are Seam managed? And does this only refer to the entities which are in the list itself or also to the component which provides the list (which should be Seam managed since it's a component, isn't it?)?

                            Thanks in advance
                            Newlukai

                            • 12. Re: EntityConverter: Entity Manager not found
                              Pete Muir Master

                              To be Seam managed the entity must be loaded with an SMPC (aka EntityManager injected with @In). You don't have to use an SMPC to load the list (in either version) but, if you don't use an SMPC and a conversation, you must implement equals on your entities. I don't think your problem has anything to do with whether your entities are Seam managed. Instead I think it is probably due to using icefaces, which the entityConverter has not had extensive (by the Seam team at least) testing with.

                              • 13. Re: EntityConverter: Entity Manager not found
                                Pete Muir Master

                                mgrouch: So your problem with the entity converter in Seam is that for it to work seamlessly you have to use an SMPC? Or that you have to have an SMPC configured to reload the entities? Or? I would prefer to understand your problem and avoid forking :)

                                • 14. Re: EntityConverter: Entity Manager not found
                                  mgrouch Expert

                                  Yes. Requirement to use SMPC is a problem for me.
                                  I load list of entities via Stateless Session EJB call (so no SMPC).
                                  The entities are reverse engineered from DB at build time by hibernate tools (so no equals() method there).

                                  Please, take a closer look at my code. Do you think solution provided by Seam for dropdowns is better than mine? So many people keep reporting issues with s:convertEntity...

                                  1 2 Previous Next