10 Replies Latest reply on Mar 29, 2008 9:20 PM by pmuir

    Nested Components and Lifecycle of EntityManager

    dro_k

      I have a session bean that calls into a service that itself calls into a DAO to access the database. (This is a large application and I had to refactor it this way for code reuse)



      @Name("mySessionBean")
      @Scope(ScopeType.EVENT) //or something else depending on usage
      @Stateless //This also can be Stateful
      public class MySessionBean implements MySession {
          @PersistenceContext //this also may be EXTENDED
          EntityManager entityManager;
          @In
          SomeService someService;
      ....
      }
      



      @Name("someService")
      @AutoCreate
      public class SomeService {
          @In
          SomeDao someDao;
      ...
      }



      @Name("someDao")
      @AutoCreate
      public class SomeDao {
          @In
          EntityManager entityManager;
      
      //do something with entityManager
      ...
      }



      What should be the ScopeTypes of the Service and DAO so their lifecycle can be dependent on the lifecycle of their client (MySessionBean) and DAO will have access to the same entityManager that was created/injected to the session bean (no matter if the session bean is stateless or stateful or the type of the entityManager is transaction or extended). I know I can just new on them and pass the entityManager to them, but that doesn't seem inline with injection methodology.


      Basically, how can I achieve a behavior equivalent to the following using Seam wiring:



      @Name("mySessionBean")
      @Scope(ScopeType.EVENT) //or something else depending on usage
      @Stateless //This also can be Stateful
      public class MySessionBean implements MySession {
          @PersistenceContext //this also may be EXTENDED
          EntityManager entityManager;
      
          SomeService someService = null;
      
          public void init() {
              someService = new SomeService(new SomeDao(entityManager));
          }
      
      ....
      }
      



      Thanks,


      Drew

        • 1. Re: Nested Components and Lifecycle of EntityManager
          pmuir

          There isn't really a concept of a dependent lifecycle in Seam.


          Probably using java objects is your best bet if you want such a concept. Or define the context for your DAO and service correctly (probably stateless).


          Also, mixing SMPC and @PersistenceContext is a bit odd, as is suggesting your @Stateless bean can be used in other contexts.

          • 2. Re: Nested Components and Lifecycle of EntityManager
            matt.drees

            I'm assuming you're not wanting to use a SMPC at all; you just want to propagate the EJB @PersistenceContext to other objects that you want to use.


            I imagine you could do something like the following.



            @Name("mySessionBean")
            @Scope(ScopeType.EVENT) //or something else depending on usage
            @Stateless //This also can be Stateful
            public class MySessionBean implements MySession {
                @PersistenceContext //this also may be EXTENDED
                EntityManager entityManager;
                @In
                SomeService someService;
            
                @Factory(value="mySessionBeanEM", scope=STATELESS, autoCreate=true)
                getEntityManager() {
                    return entityManager;
                }
            ....
            }
            



            @Name("someService")
            @Scope(STATELESS)
            @AutoCreate
            public class SomeService {
                @In
                SomeDao someDao;
            ...
            }



            @Name("someDao")
            @Scope(STATELESS)
            @AutoCreate
            public class SomeDao {
                @In
                EntityManager mySessionBeanEM;
            
            ...
            }




            Note, though, that this creates an implicit linkage (the context variable name mySessionBeanEM) between SomeDao and MySessionBean.  So, maybe not what you want.



            My second thought is something like this:






            @Name("mySessionBean")
            @Scope(ScopeType.EVENT) //or something else depending on usage
            @Stateless //This also can be Stateful
            public class MySessionBean implements MySession {
                @PersistenceContext //this also may be EXTENDED
                EntityManager entityManager;
                @In
                SomeService someService;
            
                @In
                EntityManagerProvider entityManagerProvider;
            
                public doSomething()
                {
                   entityManagerProvider.makeAvailable(entityManager);
                   someService.doSomeOperation();
                   entityManagerProvider.retract();
                }
            
            ....
            }
            



            @Name("someService")
            @Scope(STATELESS)
            @AutoCreate
            public class SomeService {
                @In
                SomeDao someDao;
            ...
            }



            @Name("someDao")
            @Scope(STATELESS)
            @AutoCreate
            public class SomeDao {
                @In
                EntityManager entityManager;
            
            ...
            }




            @Name("entityManagerProvider")
            @Scope(EVENT)
            @AutoCreate
            public class EntityManagerProvider {
               private EntityManager entityManager; //or maybe a Stack of entityManagers
            
               public makeAvailable(EntityManager entityManager)
               {
                   this.entityManager = entityManager;
               }
            
               public retract()
               {
                   this.entityManager = null;
               }
            
               @Factory(value="entityManager", scope=STATELESS, autoCreate=true)
               public provideEntityManager()
               {
                   return entityManager;
               }
            
            ...
            }




            But, ultimately, I think life is just easier if you use a SMPC.  Then you can just use @In EntityManager entityManager everywhere.  What are your reasons for not wanting to use one?

            • 3. Re: Nested Components and Lifecycle of EntityManager
              dro_k

              Thanks for the replies. I think my original post wasn't very clear. I actually do want to use SMPC, I just want to be able to encapsulate a set of database aware business logic in a separate class so I can reuse them in my actions.


              Basically:


              @Name
              @Stateless
              public ActionA {
                  @In
                  EntityManager entityManager;
              
                  @In
                  BusinessBean businessBean;
              
                  public String act() {
                      buinessBean.doSomethingUsingEntityManager();
                      ...
                  }
              }
              


              @Name
              @Stateful
              public ActionB {
                  @In
                  EntityManager entityManager;
              
                  @In
                  BusinessBean businessBean;
              
                  @Begin(flushMode=MANUAL)
                  public void startWizard() {
                      buinessBean.doSomethingUsingEntityManager();
                      ....
                  }
              
                  @End
                  public void endWizard() {
                      entityManager.flush();
                  }
              }
              



              Now how should I mark the BusinessBean



              public BusinessBean {
                  @In
                  EntityManager entityManager;
              
                  public void doSomethingUsingEntityManager() {
                      entityManager.createQuery.....
                  }
              }




              I am actually at TheServerSide Java Symposium and ran into Michael Yuan, and he suggested I try configuring using components.xml, I haven't had a chance yet (and don't know how). What do you guys think?


              Thanks,


              DK

              • 4. Re: Nested Components and Lifecycle of EntityManager
                matt.drees

                Great.  Using a SMPC, you don't need to do anything more to your code.  You just need to configure the SMPC in components.xml, as Michael said. Documentation here.


                • 5. Re: Nested Components and Lifecycle of EntityManager
                  matt.drees

                  Matt Drees wrote on Mar 29, 2008 03:31 AM:


                  you don't need to do anything more to your code.


                  By that, I mean your last set of examples.  Not your first set (with @PersistenceContext).

                  • 6. Re: Nested Components and Lifecycle of EntityManager
                    dro_k

                    Thanks for your reply, I think this makes a lot of sense now. The only thing I'm still confused about is that what's the effect of marking a POJO with both @AutoCreate and @Scope(STATELESS)?

                    • 7. Re: Nested Components and Lifecycle of EntityManager
                      dro_k

                      or more clearly, what happens when you inject a POJO which is marked with both @AutoCreate and Scope(STATELESS) to multiple components?

                      • 8. Re: Nested Components and Lifecycle of EntityManager
                        pmuir

                        The shortest scope a POJO can have is EVENT - as long as you make the POJO stateless (i.e. don't put any data into non-bijected fields), it will act as a stateless component.

                        • 9. Re: Nested Components and Lifecycle of EntityManager
                          dro_k

                          Thanks Pete. One thing that still remains is that what happens when you inject an @AutoCreated POJO with Scope EVENT that has an @In EntityManager, into let's say a SFSB with Scope of CONVESATION and a MANUAL flush mode. Will Seam use the same EntityManager from SFSB and inject into the POJO, eventhough they have different scopes?

                          • 10. Re: Nested Components and Lifecycle of EntityManager
                            pmuir

                            Yes