4 Replies Latest reply on Apr 1, 2009 6:27 AM by Stuart Douglas

    Different entitymanagers with EJBs and Seam EM

    asaf sh Expert

      Hello,


      I am having some standard EJBs with EntityManagers injected by @PersistenceContext,


      When using these EJBs, sometimes I would like to override the EJB's standard EntityManager with Seam's Conversational EM,



      So in my EJBs, I don't use the '@PersistenceContext', but instead I use:


      @PersistenceUnit
      private EntityManagerFactory factory;
      



      And factory the entity manager when necessary by: factory.createEntityManager(); (whenever there's no Seam's EM set manually so the EJB can work when detached from Seam use)


      Apparently, the behavior is different, as I started to get exceptions such as:
      A detached entity passed to persist



      I assume that somehow the AS is smart enough to inject the right EM even though I use different EJBs for loading/persisting.



      Is there a correct way to create entity managers as the AS would do as when using 'PersistenceContext' ? maybe the factory is not the right way here.




      I know that this is not exactly related to Seam, but I assume that sometimes, when migrating from EJBs to Seam people might have the same problem as I do,




      Many thanks,



      Asaf.

        • 1. Re: Different entitymanagers with EJBs and Seam EM
          Norman Richards Expert

          I'm not sure what your question is, but using an app server managed persistence context and a Seam-managed persistence context are two completely different things.

          • 2. Re: Different entitymanagers with EJBs and Seam EM
            asaf sh Expert

            Let me explain,


            I have a general EJB that manages few things (sometimes invoked via Seam code, sometimes not)
            But when I'm inside seam context and use EJB, I loose the conversational enhancements, and gets a lot of Lazy fetch exceptions, I set Seam's entityManager sometimes manually into the EJB and then invoke its methods that way my EJB logic stays the same and enhanced with Seam's EM when neccessary.


            So all the methods in the EJB retrieve entityManger by invoking the getEntityMangaer() method that looks like that:



            
            @PersistenceUnit
            private EntityManagerFactory factory;
            
            public EntityManager getEntityManager() {
              if  ( (entityManager == null) || (!entityManager.isOpen()) ) {
                entityManager = factory.createEntityManager();
              } 
                      
              return entityManager;
            }
            




            But as it seems, the behavior of factory.createEntityMangaer() is different then the behavior when using:


            @PersistenceContext
            public EntityManager entityManager;
            



            That makes AS inject the entityManager by its own, as at the moment I started to use 'factory.' I'm getting errors related to a usage of different entityManagers. again, probably the AS is smart enough to inject the correct one that contains my managed entities.



            I'm seeking for a replacement of the factory that simulates the way the AS injects the entityManager but by code and not via the annotation,






            Thanks,


            Asaf.

            • 3. Re: Different entitymanagers with EJBs and Seam EM
              Arbi Sookazian Master

              use @In to inject Seam container managed persistence context (SMPC).


              use @PersistenceContext to inject EJB container managed persistence context.


              AFAIK, your EJB implementation is independent of what method you use for EntityManager injection as the injection method is merely metadata (in this case annotations).


              Are you saying you sometimes need to use @In and sometimes use @PersistenceContext?


              Why do you need to even use @PersistenceUnit?  That annotation is not even referenced in the Seam 2.1.1.GA ref doc.


              it's configured like this in components.xml:


              <persistence:managed-persistence-context name="entityManager"
                                                   auto-create="true"
                                    persistence-unit-jndi-name="java:/fooEntityManagerFactory"/>


                  

              • 4. Re: Different entitymanagers with EJBs and Seam EM
                Stuart Douglas Master

                The Application server will inject a transaction scoped EntityManager, you are getting a brand new entityManager, which is why you are having problems. If you absolutely must get an entityManager programatically you have to look it up in JNDI, the spec has the following example:


                @Stateless
                @PersistenceContext(name="OrderEM")
                public class MySessionBean implements MyInterface {
                     @Resource SessionContext ctx;
                     public void doSomething() {
                          EntityManager em = (EntityManager)ctx.lookup("OrderEM");
                          ...
                     }
                }