5 Replies Latest reply on Oct 27, 2005 8:05 AM by murtuza52

    EntityManager & rollback

    jc7442

      I wrote the following code:

      @TransactionAttribute(TransactionAttributeType.REQUIRED)
       public void m1() {
       AnEntityBean bean= new AnEntityBean ();
       manager.persist(bean);
       try {
       // m2 has a transaction type set to mandatory
       aSessionBean.m2();
       } catch (Exception e) {
       System.out.println("Rollback :"+ctx.getRollbackOnly());
       }
       AnEntityBean bean 2= new AnEntityBean ();
       manager.persist(bean2);
       }
      


      When aSessionBean.m2() throws a RuntimeException, it rollbacked the JTA transaction. Consequently, when I try to persist bean2, I have the following exception:
      javax.persistence.TransactionRequiredException: Transaction must be active to access EntityManager

      RuntimeException has rollbacked the JTA transaction. But when I have a look into database, I can see that bean1 has been persisted. It seems that EntityManager has not been rollbacked properly, it has just been close on the exception.

      Is it a bug in the implementation ?

      I use JBoss4.0.0rc, EJB3 rc2 and MySql.

        • 1. Re: EntityManager & rollback
          murtuza52

          I have similar situation where functions are as follows:

          @TransactionAttribute (TransactionAttributeType.REQUIRED)
           public MessageObject fun1() throws Exception {
           manager.persist(data);
           fun2(); //where fun2 has REQUIRED transaction type and throws exception
           }
          


          Upon testing i found that when fun2 throws exception, transaction is not rolled back and "data" is persisted. In different thread i found that this is normal behaviour, then how can be best achieve the rollback or commit upon normal exit from the function.

          Murtuza

          • 2. Re: EntityManager & rollback
            murtuza52

            Hello,

            I tried few more example to make sure TransactionAttribute is functioning correctly. I have entity B inherited from A with JOINED strategy. Another entity Y inherited from X with JOINED strategy.

            A<-------B and Y--------->X

            I am trying to achieve following:
            1. Persist B if only persist Y was successful else rollback
            2. Merge B if only merge Y was successful else rollback

            Since the real code is very long, i'll try to define the logic and some code here. Two stateless session beans C and Z. as follows

            
            @Stateless
            public class CBean implements C{
            
             private @PersistenceContext
             EntityManager manager;
            
             @EJB Z z;
            
             @TransactionAttribute(TransactionAttributeType.REQUIRED)
             public MessageObject Fun1() throws Exception{
             try{
             manager.persist(B)
             z.fun1(Y);
             // throw new KException("Simulate rollback"); [Mark 1]
             }catch(Exception err)
             {
             System.out.println("Rolled back");
             throw new KException("Could not add A"); //[Mark 2]
             }
            
             }
            
            }
            
            
            @Stateless
            public class ZBean implements Z{
            
             private @PersistenceContext
             EntityManager manager;
            
             @TransactionAttribute(TransactionAttributeType.REQUIRED)
             public MessageObject Fun1(Y y) throws Exception{
             manager.persist(y)
             //throw new KException("Simulated rollback from Z");
             }
            
            }
            
            @ApplicationException(rollback=true)
            public class KException extends Exception{
             KException(String msg){
             super(msg)
             }
            }
            


            Unfortunately all possible combintaion of throwing Exception that is from C, Z and real runtime exception generated by passing duplicate primary key for Y will not roll back will not rollback B (which was already persisted). B is always persisted at both Mark 1 and Mark 2 when simulated.

            Is this a bug or what am i doing wrong? Is TransactionAttibute support for inheritence? I'll appreciate if anyone can help me as i am stuck here.

            Is there any other approach i can acheive same as i cannot use em.getTransaction()..begin()/.commit()/.rollback(). It throws exception saying invalid function call, cannot make this call for managed bean.


            • 3. Re: EntityManager & rollback
              murtuza52

              I am using WindowXP, JBoss AS 4.0.3, EJB RC3, Eclipse 3.1

              • 4. Re: EntityManager & rollback
                jc7442

                According to spec, unchecked exception (RuntimeException) rollback the transaction and checked exception does not rollback the transaction.

                In my case, I was using MysQL 4.x. It does not support rollback. If I use Postgresql, it works fine. My problem was not due to EJB3 implmentation but it was due to the underlying database.

                • 5. Re: EntityManager & rollback
                  murtuza52

                  You are damn right, I switched from MySQL 4.1 to 5.0 and the application works great. I never thought the problem would be database.

                  Thanks and EJB3 rocks.

                  Murtuza