views:

31

answers:

1

I'm having one issue that is how to catch OptimisticLockException in web layer (.war code) when it is raised by the EJB layer.

We are using JEE5, GlassFishV2.1 and JPA (with TopLinks)and Container Managed Transactions.But when the dirty read occur due to trnasaction by another concurrent user on the same entity.It gives Transaction.RollBackException at the war layer which is actually caused by OptimisticLockException.But i am unable to catch OptimisticLockException at war side.

I found on internet
http://books.google.com/books?id=fVCuB_Xq3pAC&pg=PA292&dq=OptimisticLockException++Collision+Exception&hl=en&ei=0A6jTI3nN5DQccbO5MAB&sa=X&oi=book_result&ct=result&resnum=1&ved=0CCgQ6AEwAA#v=onepage&q=OptimisticLockException%20%20Collision%20Exception&f=false

that use of em.flush on ejb side and then we can catch and throw some custom exception to war. but I think em.flush will refresh all database, is it an expensive operation or not?

try{
   //some enitity
   em.flush()
  }
catch(OptimisticLockException ole){

throw ole;
}

My opinion is not to call em.flush as 90% of cases there will be no OptimisticLockException and to catch the EJBException in the .war and then retry it. Is there a better option?

try{ // some code } catch (EJBException ex) {

      if (ex.getCausedByException().getCause().toString().
          indexOf("javax.transaction.RollbackException")!= -1){
               // do work
          }     
      }
   }
A: 

You could do either. flush() is not technically an expensive operation, as the work it does in writing to the database no longer needs to be done by the commit, so there is no extra database access, and does not "refresh all database". flush() does have some overhead though, the changes will be computed twice, once for flush and once for commit, vs once with commit. Depending on your change policy and number of managed objects, this does have a cost. Flush also needs to put the managed objects back into a tracked managed state, which also has some cost, but generally minor compared to the database access cost.

Note that other errors could occur during a commit than a lock error, so even if you use a flush to catch the lock error, you still need code in your war to handle other causes of failure, so not using the flush, and just having general transaction failed error handling may be the best solution. If you want to do something special for a lock error, you should be able to find the exception in the cause by chain, but be careful in just retrying the operation, you are locking for a reason, so should probably report the error to the user and have them retry their operation.

James