EJB programming & troubleshooting: Transactions
I have a simple question that does not seem to have a simple answer since I hear different things from different people. Simply put, I would like to know what steps need to be taken in rolling back a transaction. I believe that any subclass of RuntimeException, most notably EJBException, triggers a rollback, but what does that mean exactly? Does throwing the exception by itself cause the rollback? Or does one have to explicitly call setRollbackOnly() on the SessionContext? And if the latter is the case, what is the point then of CMT? If I have to write transactional code anyway, I could just as easily write it in BMT, couldn't I?
Any guidance is appreciated. Thanks.
Here's my understanding, although as it is late in the afternoon, I might not be remembering correctly. The following applies to container-managed transactions:
1. Any exception thrown from an EJB method that is derived from RuntimeException will cause an automatic rollback of the entire transaction. I believe that this is the functionality with EJBException because I think it is derived from RuntimeException.
2. An application-level exception (not derived from RuntimeException) will not cause an automatic rollback because it is expected that the EJBs will capture the exception and handle the error on their own or attempt to repair the transaction. In this case, to perform a rollback, the EJB must manually call setRollbackOnly().
I think that is the way that it works.
Michael is correct. However it's important to note that an EJBException, or other runtime exception, not only causes the current transaction to roll back but causes the EJB container to discard the offending bean instance. The instance will not service further requests.
There is typically no need to catch runtime exceptions in EJBs--even to wrap them in EJBExceptions--if they are truly fatal.
My new book, Expert One-on-One J2EE discusses EJB error handling in detail--both how it works and best practices.
Thanks, Michael and Rod. I appreciate your help. But to elaborate on your point, Rod, about the offending bean instance being destroyed upon rollback, I have found a problem. It seems any entity beans that are created in association with the inserts of records into the databse remain while the actual database records are deleted with the rollback. Say, for example, an entity bean was used to make an insert into the database of a record with primary key 6. The insert occurs but is later rolled back because of an error in subsequent processing. So now there is no record with PK 6. When an attempt is made to insert a new record with that PK, I am receiving a DuplicateKeyException in the home.create() method. So it seems the entity bean instance asociated with the record that was rolled back in the first bad transaction remains while the rows do not. How can I kill not just the offending bean instance but all others associated with a failed transaction as well?
Thanks again for your help, guys.