6 Replies Latest reply on Mar 10, 2010 12:10 PM by nimo stephan

    Does Seams entityManager disturbs TransactionAttributes in EJB ?

    nimo stephan Master

      I want to update a Set of Entities.




      A Entity should be in exactly one Transaction.





      So I use this code in my stateless session bean:





      @Stateless
      @Name("mySessionBean")
      @TransactionManagement(javax.ejb.TransactionManagementType.CONTAINER)
      public class MyEJBBean implements MyEJBLocal {
      
      @In (create=true) private EntityManager entityManager;
      
      public void updateUsers(Set<Users> users)
      {
         for(User u: users){this.updateUser(u);}
      }
      
      // the user-instance should be in exactly one transaction !
      @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
      public void updateUser(User u)
      {
      
      u.setProperty("test");
      
      // I have to call explicitly flush, as the caller-bean is a conversation-bean with FlushModeType.MANUAL
      entityManager.flush();
      
      }




      the updateUsers-Method is called within a conversation-scoped seam-component:



      @Name("myConv")
      @Scope(CONVERSATION)
      public class MyConv{
      
      @In(create=true) MyEJBLocal myEJBLocal;
      
      @Begin(join = true, flushMode = FlushModeType.MANUAL)
      public void initUpdateUsers()
      {
      
      // I call the updateUsers-Method
      myEJBLocal.updateUsers(this.getUsers());
      
      }




      My Question is:


      Is this okay?
      I am not sure, if all User-Objects have really their own transactions.
      How can I test it?


      Does Seam interrupts the normal Transaction by using Seams entityManager:




      @In private EntityManager entityManager;




      or by using Seams flushMode-ability:




      flushMode = FlushModeType.MANUAL




      Should I favour UserTransaction instead of


      javax.ejb.TransactionAttributeType.REQUIRES_NEW



      ?

        • 1. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
          Arbi Sookazian Master

          Generally speaking in a JSF/Seam/EJB3/JPA/Hibernate app, you should use EJB CMT (container-managed tx's), SMPC and Hibernate manual flush.


          Read SiA or JPwH books for details...

          • 2. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
            Stuart Douglas Master

            This is not really ok. The EM is enlisted in the outer transaction, not the new one, so this will not do what you expect.


            Use @PersistenceContext() instead to get a transaction scoped em and merge your entity (This is in the seam docs somewhere).



            This may get fixed in Seam 3.

            • 3. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
              nimo stephan Master

              Hello Stuart,


              I do not understand that.


              Actually I am using CMT with SMPC and Seams manual flushing.


              The first thing which I do not understand, is this:


              entityManager.getFlushMode() returns AUTO
              and hibernates session.getFlushMode() returns AUTO, too.
              But I have manual-flushing enabled with seams flushMode: FlushModeType.MANUAL.


              So where lies the difference of seams manual flushing and hibernate manual flushing?
              Why does hibernate does not tell me that flush-mode is manual?



              The other question is:



              The EM is enlisted in the outer transaction, not the new one, so this will not do what you expect.

              The caller is my conversation bean. The entityManager is within the EJB Session Bean.
              I delete this:


              @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)



              and trigger initUpdateUsers, then it works. The manual flushing works. So there is no need to use @PersistenceContext. Am I right?


              According to Seam manual (page 201):



              ..Therefore, if you mark a method REQUIRES-NEW then you should access the entity manager using @PersistenceContext.

              Would it be better to use


              @PersistenceContext(type=EXTENDED)
              private EntityManager em;



              with Hibernate manual flushing instead of SMPC and Seams manual flushing ?

              • 4. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
                nimo stephan Master

                I have tested the seams manual flush and used that before a lot without problems.


                Now, I have a long running method which calles other methods and the flush is only called at the end of this long running method.


                But however, I can see in my log, that the flush is called randomly - even I do not trigger it by myself. So whats going on?


                I definitly use seams manual flush-option and can see that the flush is for example called before using a createNamedQuery to get results from the database. How can I really enforce that flush is only called when I call entityManager.flush() ?


                Does Seam automatically calls flush if memory is close? Or are their any limitations when manualFlush does not work??

                • 5. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
                  nimo stephan Master

                  Okay I found the problem:


                  Hibernate Docu





                  3.9. Flush the persistence context
                  3.9.1. In a transaction

                  From time to time the entity manager will execute the SQL DML statements needed to synchronize the data store with the state of objects held in memory. This process, flush, occurs by default (this is Hibernate specific and not defined by the specification) at the following points: 
                  - before query execution
                  - from javax.persistence.EntityTransaction.commit()
                  - when EntityManager.flush() is called


                  I have indeed some queries within my long span method and before query excecution, Hibernate forces a flush even Seams flush-Mode is manual.


                  So how can I avoid that? Should I use UserTransaction to ensure that the commit is only called once? I need to ensure that all updates and inserts of a method lies in exactly one transaction.






                  • 6. Re: Does Seams entityManager disturbs TransactionAttributes in EJB ?
                    nimo stephan Master

                    The only interesting question is:



                    Does JPA/Hibernate ensures that a rollback really rollbacks ALL flushed datas?

                    For example:


                    @Stateless
                    @Name("myBean")
                    public class EJBBean{
                    
                    @Resource private SessionContext context;
                    
                    // Here begins the transaction?!
                    public void update(){
                    
                    
                    this.updateUser();
                    
                    }
                    
                    public void updateUser(User u)
                    {
                    
                    u.setName("test");
                    
                    // flush is called automatically because of a query (according to hibernate docs) !
                    List<Hobby> hobbies= (List<Hobby>) entityManager.createNamedQuery(...);
                    
                    
                    if(updateYes) this.end();
                    
                    if(updateNo) context.setRollbackOnly();
                    }
                    
                    
                    public void end()
                    {
                    
                    entityManager.flush();
                    }
                    
                    }