1 Reply Latest reply on Aug 10, 2008 1:32 AM by romendo

    EntityManager injection (JPA, Hibernate, Tomcat)

    romendo

      Hi there,


      I am using Seam with JPA and Hibernate in Tomcat. I am using a custom DataModel in order to provide paging, sorting, and filtering. The code has originally been developed for use with Tomahawk DataTable. I am now in the process of moving this from MyFaces to Seam.


      In the old version I used a ThreadLocal variable to store the EntityManager and corresponding Hibernate Session. However, this does not work with Seam. That's why I have added the following to components.xml:



      <factory name="session"
               scope="STATELESS"
               auto-create="true"
               value="#{em.delegate}"/>



      I then attempt to inject the session into a JavaBean that has session scope. The JavaBean is used to access the DataModel:


      @DataModel
      protected FilterablePagedDataModel<Object> dataModel



      I also use a custom DataModels object in order to support the DataModel instances with @DataModel:



      @Name("org.jboss.seam.faces.dataModels")
      @Install(precedence=FRAMEWORK)
      @Scope(STATELESS)
      @BypassInterceptors
      public class CustomDataModels extends DataModels {
           
           @Override
           public DataModel getDataModel(Object value) {
                if (value instanceof DataModel) {
                     return (DataModel) value;
                } else {
                     return super.getDataModel(value);
                }
           }
      }



      Everything seems to work fine except for one thing. The session gets reset to null. Using the debugger I see the following is happening:




      1. session gets injected properly.

      2. the getDataModel of my JavaBean is called (this does not yet load any data)

      3. session gets injected again, this time as null.

      4. HtmlDataTable.isRowAvailable() gets called: Since no data has been loaded yet the JavaBean attempts to load data. Since the session is null this fails with a NPE.

      5. session gets injected properly.

      6. HtmlDataTable.getRowCount() gets called from DataModelBinder.getSelection(DataModel,DataModel).

      7. the getDataModel of my JavaBean is called

      8. finally data is loaded via DataModelBinder.getWrappedData.

      9. session gets injected again, this time as null

      10. session gets injected properly yet again

      11. session gets injected again, this time as null



      The end result is the display of the error page with the NPE as reason.


      I use a redirect when accessing the page that contains the dataTable.


      My question: Why does Seam inject the session with value null? Is there anything I can do to avoid that?


      Thanks,
      Roland

        • 1. Re: EntityManager injection (JPA, Hibernate, Tomcat)
          romendo

          I think I have found the reason for the behaviour I have seen. The JavaBean that contains the @DataModel is of scope SESSION. The data model is initialized only once by a method I annotated with @Factory. However, the user clicks on the data scroller for the table the table is rerendered without accessing the data model through the JavaBean. It seems to directly call a method of the data model that retrieves the next page of data. At that point the JavaBean is not accessed. Hence, the session is not injected.


          1. Is there a way to always execute my @Factory method similar to @Unwrap but for a @DataModel?


          2. How can I access the current EntityManager (or Hibernate session) object from within my data model?


          Thank you for your help,
          Roland