5 Replies Latest reply on Sep 4, 2011 3:36 PM by gebuh

    Read-Only EntityManager in ScopeType.Stateless

    mugwump

      I have a list of constants, that I try to initialize in a @Scope(ScopeType.STATELESS) managed component: These components are @AutoCreate'd at the start of the application and need access to the database: As I am in a war, simply injecting an EntityManager with



      @In
      EntityManager;


      results in a required-value exception, as there is no EntityManager in the STATELESS-Scope. Using a PersistenceContext also does not work, as this works only in a SFSB/SLSB. Only chance here is to move the component into ScopeType.CONVERSATION, but then the initialization is unnecessarily triggered for every conversation.


      What I really need is a read-only entityManager, that is accessible outside a conversation - is there any way to achieve this in seam2.2 in a war?!


      thx for any help,
      Stefan

        • 1. Re: Read-Only EntityManager in ScopeType.Stateless
          cosmo

          I don't know if I am getting this right but maybe your entity manager is misconfigured because it can be surely injected in a stateless POJO.
          Anyways, be sure to have the same variable name that what is declared in components.xml.


          For instance, if you have


           <persistence:managed-persistence-context auto-create="true"
            name="entityManager" ...



          This will work


          @In EntityManager entityManager



          whereas



          @In EntityManager em




          wont.

          • 2. Re: Read-Only EntityManager in ScopeType.Stateless
            mugwump

            It works now (there was something else wrong, the missing entitymanager was only a side-effect): But I am still getting warnings:


            10:20:05,699 WARN  [Component] Cannot create Seam component, scope is not active: entityManager(CONVERSATION)


            Here is what I'm doing:


            1. Create a list of constant-values from the database with:





            @Name("regions")
            @Scope(ScopeType.APPLICATION)
            @Startup
            public class Regions{
            
                 private List<Region> regionsList; 
                 
                    @In(value="entityManager")
                 EntityManager entityManager;
                 
                    @Unwrap
                 public List<Region> getRegions(){
                      
                      if (regionsList == null){
                           regionsList = getEntityManager().createQuery("select r from Region r").getResultList();
                      }
                      
                      return regionsList;
                      
                 }
            }
            






            2. Define a Session-Scoped bean, into which I inject these constants:




            @Name("benchmarkGUIModel")
            @Scope(ScopeType.SESSION)
            @AutoCreate
            public class BenchmarkGUIModel extends GUIModel{
            
                    @In(value="regions")
                 private List<Region>                regionList;
            
            ...
            
            




            Now the @Startup of Regions brings up a warning:


            10:18:13,026 WARN  [Component] Cannot create Seam component, scope is not active: org.jboss.seam.international.localeSelector(SESSION)


            which I assumes comes from the fact that somewhere in the dependency chain of Regions appears a locale.


            But the other warning looks worse, which is fired, when the BenchmarkGUIModel is accessed:


            10:20:05,715 WARN  [Component] Cannot create Seam component, scope is not active: entityManager(CONVERSATION)


            which comes probably from the fact that I am using the same entityManager in the Regions, which is application-scoped and in the BenchmarkGUIModel, which is Session-scoped.


            Do I really need two entity-managers, one for application-scoped Beans, one for the others?!


             

            • 3. Re: Read-Only EntityManager in ScopeType.Stateless
              mugwump

              Using two EntityManagers (one session-scoped, one stateless) does not really help. Now I am getting:




              Caused by: java.lang.NullPointerException
                      at org.jboss.seam.persistence.ManagedPersistenceContext.initEntityManager(ManagedPersistenceContext.java:82)
                      at org.jboss.seam.persistence.ManagedPersistenceContext.getEntityManager(ManagedPersistenceContext.java:108)
              



              when I try to access a property on the session-scoped bean.


              Does anyone have a working setup for this scenario?!


              • 4. Re: Read-Only EntityManager in ScopeType.Stateless
                mugwump

                Just to wrap this topic up: You need two EntityManager and the correct Factories, both correctly scoped. This is what I have currently configured in components.xml:



                <!-- This is the regular factor/Context -->
                <persistence:entity-manager-factory
                          name="myPersistenceUnit" />
                <persistence:managed-persistence-context
                          auto-create="true" 
                          entity-manager-factory="#{myPersistenceUnit}"
                          name="entityManager" />
                
                <!-- this is a read-only EntityManager that is used for constants only-->
                <persistence:entity-manager-factory
                          scope="application"
                          persistence-unit-name="myPersistenceUnit"
                          name="constantsFactory" />
                <persistence:managed-persistence-context
                                auto-create="true" 
                          scope="application"
                          entity-manager-factory="#{constantsFactory}"
                          name="constantsEntityManager" />
                



                and then inject the right entityManager into your Application-Scoped POJOs:


                @In(value="constantsEntityManager")
                EntityManager entityManager;
                



                The proper naming here ensures, that you don't get an EntityManager from a wrong scope, which prevents the above warnings and NullPointerExceptions.

                • 5. Re: Read-Only EntityManager in ScopeType.Stateless
                  gebuh

                  Stefan, what was it that wouldn't allow you to get an entityManager in the first place?  I'm not able to inject an entityManager into POJO's at all.