Discussions

EJB programming & troubleshooting: transaction problem

  1. transaction problem (4 messages)

    I have a jsp call stateless session ejb method,in the method,it call a stored procedure,the stored procedure call
    master..xp_cmdshell
    and update some tables.

    since use user doesn't have permit to access master database,the
    master..xp_cmdshell
    failed.but the tables updated

    I set the ejb and method have transaction attribute as "required",if the part of store procedure failed,why the container didn't roll back the transaction?
     
    I'm using JBoss3.2.3, MS sql server 2000, and master..xp_cmdshell execute a bcp command,copy from table to a file

    Threaded Messages (4)

  2. transaction problem[ Go to top ]

    ...if the part of store procedure failed,why the container didn't roll back the transaction? ...
    Only RuntimeExceptions lead to a rollback. A checked exception - and SQLException *is* a checked Exception! - does not rollback. For this, you have to write one of the following two things:

    ----

    try {
       ...SQL call...
    } catch (SQLException ex) {
       sessionContext.setRollbackonly();
       throw new ApplicationException(ex); // [1]
    }

    [1] Dont throw SQLException into your JSP - the JSP shouldn't know about whether you use SQL or some other technology for persistence; or, for that matter, persistence at all.

    ----

    try {
       ...SQL call...
    } catch (SQLException ex) {
       throw new IllegalStateException(ex.getMessage()); // [2]
    }

    [2] This is a "reuse" of a java.lang exception. This is "more or less ok" if you assume that a problem in the SQL call is a "system problem" which should never happen in a correctly installed system.
    An alternative to IllegalStateException is to use EJBException - which, IMO, has a next-to-nothing meaning of "something happened in some EJB thing".
    A probably more beautiful design is to define your own RuntimeException.

    ----

    A third possible approach is to let the exception bubble up to the JSP and call setRollbackOnly() there. I dont know exactly how you get the necessary Context there, but it's possible (and you will get the same UserTransaction if you declare "required" on the SessionBean). But from a design standpoint, this is wrong: The decision to rollback should be made in your *business logic* - i.e., the SessionBean -, not in some client using the business logic (in your case the JSP).


    To sum it up: Use the first approach if an exception in the SQL call is an accepted behavior (e.g. because the database checks for constraints). Use the second approach (with the IllegalStateException/EJBException/your RuntimeException) if in a correctly running system, the SQLException "cannot happen" (e.g. because you check for perfect parameters in the JSP or in the SessionBean before the SQL call).

    - I hope I got it right ;-)

    Regards
    Harald M. Mueller
    Germany
  3. transaction problem[ Go to top ]

    Thank you for your reply
    I think the application server should take care of the transaction since I 'm using container managed transaction :
    <transaction-type>Container</transaction-type>
    also,this is the benefit to use EJB,right?
    if so,why I still need code to say setRollbackonly()?
  4. transaction problem[ Go to top ]

    Thank you for your reply. I think the application server should take care of the transaction since I 'm using container managed transaction :<transaction-type>Container</transaction-type>also,this is the benefit to use EJB,right?if so,why I still need code to say setRollbackonly()?
    Didn't I explain it?: If a checked exception (a non-RuntimeException) is thrown, the server will not rollback the transaction. That's just in the specification of EJB.

    The server does take care of the transaction: It commits it. If you do not want this, you must tell it - either by calling setRolbackonly(), or by forcing a RuntimeException (e.g. EJBException).

    Regards
    H.M.Mueller
    Germany
  5. As Mr H.M.Mueller has put it, if you believe that the process of rollback should be done by the server and not by you by calling the Context.setRollBackOnly(). you should simply make sure that the exception that is thrown by the session bean method is a runtime exception.