Transcation not Rollbacked in Container Managed Transcation

Discussions

EJB design: Transcation not Rollbacked in Container Managed Transcation

  1. I have two session bean X,Y which do some database operation.And in my deployment descriptor I have set transcational attribute as Required, as well as transcation type as Container.In this session bean am throwing an
      new java.rmi.RemoteException() if condition is not satisfied(inorder to rollback .Am i right!!).
      Suppose if anyone dosn't satisfies the condition it throws execption.

    I have another M bean which calls the other two
    session bean(X,Y).And in my deployment descriptor I have set transcational attribute as Required, as well as transcation type as Container.

    If any one of two session bean(X,Y) doesn't satisfies the condition it throws exeception.Am caughting in the bean(M)
    and roolbacking like this
              try{
                   x.method1();
                   y.method2();
              }
              catch(java.rmi.RemoteExcveption e){
                   sessioncontext.setRollbackOnly();
                   throws new java.rmi.RemoteException();
              }
    Am i right....
    But I couldn't achieve the transcation concept.I mean even one gets fails other gets committed.

    ie Even if y.method2() throws an exception, database operation on x.method1() is succedding(committed).
    What should I do inorder to work well.

    Anyone help in this regard
    Thanks in advance
    With Regards,
    Vinoth.c
  2. REQUIRES attribute of transaction is standalone . To make it a part of the whole transaction make the other two baens transaction attribute as "SUPPORTED" that way they will support the calling bean's transaction.
    vivek sharan
  3. What is your app server? Database? JDBC driver? Are you using the same database connection pool in beans X and Y?
  4. Applicaton server is weblogic.Database sybase sqlserver.
    Driver is jconnect4.2.Am using same connection pool on the
    X and y beans.
  5. I think that instead of throwing the RemoteException, you should throw the EJBException. In order to make sure that Container rollbacks your transaction, you must throw the System exception. Once you throw the EJBException then container will rollback your transaction and wrap your exception into the RemoteException and throw to the client.

    throw new EJBException("Exception: " + ex.getMessage());
       
    Another thing you can do is:
    before throwing the exception call setRollBackOnly on the SessionContext instance.

    I hope this will help...

    Thanx
    Sanjeev
  6. M bean
    ------

    public void setSessionContext(SessionContext ctx){
    this.ctx = ctx;
    }

    public boolean transferSTtoCT(String name1,String name2,int amount) throws EJBException{

     CitiBankHome citiHome=(CitiBankHome)ic.lookup("citicorp");
     CitiBank citiRemote=citiHome.create();
     StandardHome standHome=(StandardHome)ic.lookup("standard");
     Standard standRemote=standHome.create();

     standRemote.debit(name1,amount);
     citiRemote.credit(name2,amount);
    }
    catch(EJBException re){
       ctx.setRollbackOnly();
       throw new EJBException("Transcation "+re.getMessage());
    }
    catch(Exception e){
       System.out.println("Exception in lookup"+e);
    }
    }

    M bean ejb-jar file
    -------------------

    <transaction-type>Container</transaction-type>
     </session>
        </enterprise-beans>
        <assembly-descriptor>
          <container-transaction>
           <method>
    <ejb-name>GlobalBean</ejb-name>
    <method-intf>Remote</method-intf>
    <method-name>transferSTtoCT</method-name>
             <method-params>
    <method-param>java.lang.String</method-param>
    <method-param>java.lang.String</method-param>
    <method-param>int</method-param>
    </method-params>
    </method>
    <trans-attribute>RequiresNew</trans-attribute>
          </container-transaction>

    X bean
    -------


    public boolean credit(String name,int amount) throws EJBException{
      try{
         //loading driver
        sql="select citibank where name='"+name+"'";
        java.sql.ResultSet result=null;
      
        result=stmt.executeQuery(sql);
          while(result.next()){
    temp=result.getInt(1);
          }
       }
       catch(Exception e){
    java.lang.System.out.println("Ex"+e);
       }
       if(temp == 0){
    throw new EJBException();
       }
       amount=temp+amount;
       sql="update citibank set amount="+amount+" where
       name='"+name+"'";
     
      try{
        PreparedStatement pstmt=con.prepareStatement(sql);
        flag=pstmt.executeUpdate();
      }
      catch(Exception e){
         java.lang.System.out.println("Ex"+e);
      }
      if(flag == 1)
    return true;
      return false;
    }

    X bean's ejb-jar
    -----------------

    <transaction-type>Container</transaction-type>
    <trans-attribute>Required</trans-attribute>

    Y bean
    ------
    same as X bean but this will debit the amout

    y bean's ejb-jar
    -----------------

    <transaction-type>Container</transaction-type>
    <trans-attribute>Required</trans-attribute>

    I couldn't able to accomplish the transcation concept.May anyone tell me where I have made mistake
    Thanks in advance.
    with Regards,
    Vinoth.C
  7. Hi,
      you r not able to acheive the transaction integrity between the two methods, because, the two methods are not running in the same transaction context.

      Remember that the 'REQUIRED' attribute makes the container start a new transaction if the client doesn't supply one. which is exactly happening in ur case.

      The solution for ur problem wud be to start a client transaction in ur M bean.

      javax.transaction.UserTransaction utx = ctx.lookup
                        ("javax.transaction.UserTransaction");
    try{

      utx.begin();
      standRemote.debit(name1,account1);
      citiRemote.credit(name2,account2);
      utx.commit();

    }catch(Exception e){
      ctx.setRollBackOnly();
      utx.rollback()
    }

    hope this helps.
    thx,
    Manohar(manoharm at planetasia dot com)
  8. Doess "citicorp" points to a transactional datasource specified in the weblogic 5.1's properties file? WLS 5.1 does not support distributed transactions, and I don't know whether this is the case (my understanding is you have to be using 2 databases for the transaction to be considered distributed). Have you tried a different JDBC driver other than JConnect (I am not familiar with Sybase)? How about simply re-throw the EJB exception in your first catch block and see whether the transaction gets rolled back and go from there.