How to catch OptimisticLockException in servlet level?

3.8k views Asked by At

I'm using JPA toplink-essential, building REST web app.

I have a servlet that find one entity and delete it.

Below code I thought I could catch optimistic lock exception in servlet level but its not! Instead RollbackException is thrown, and that's what documentation says:

But then when I see the Netbean IDE GlassFish log, somewhere, optimisticLockException is thrown. It's just not being caught in my code. (my system print message doesn't get displayed so I'm sure its not going in there.)

I tried to import each packages (one at a time of course) and tested with catch clause but both time, it is not going into the catch block even though log error says "optimistic exception".

import javax.persistence.OptimisticLockException;
import oracle.toplink.essentials.exceptions.OptimisticLockException;

So where the OptimisticLockException is thrown?????

@Path("delete")
@DELETE
@Consumes("application/json")
public Object planDelete(String content) {

   try {
            EntityManager em = EmProvider.getInstance().getEntityManagerFactory().createEntityManager();

            EntityTransaction txn = em.getTransaction();
            txn.begin();
            jObj = new JSONObject(content);
            MyBeany bean = em.find(123);

            bean.setVersion(Integer.parseInt(12345));
            em.remove(bean);


            //here commit!!!!!
            em.getTransaction().commit(); 
        }
        catch(OptimisticLockException e) {  //this is not caught here :(
            System.out.pritnln("here");
            //EntityTransactionManager.rollback(txn);
            return HttpStatusHandler.sendConflict();
        }
        catch(RollbackException e) {
            return HttpStatusHandler.sendConflict();
        }
        catch(Exception e) {
            return HttpStatusHandler.sendServerError(e);
        }
        finally {
            if(em != null) {
                em.close();
            }
        }

Error msg:

[TopLink Warning]: 2011.01.28 05:11:24.007--UnitOfWork(22566987)
--Exception [TOPLINK-5006] 
(Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): 
oracle.toplink.essentials.exceptions.OptimisticLockException

    [TopLink Warning]: 2011.02.01 08:50:15.095--UnitOfWork(681660)--
javax.persistence.OptimisticLockException: Exception [TOPLINK-5006] (Oracle TopLink 
Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): 
oracle.toplink.essentials.exceptions.OptimisticLockException
3

There are 3 answers

4
esaj On BEST ANSWER

Not 100% sure, but could it be that you're catching javax.persistence.OptimisticLockException (notice the package), but as the thrown exception is oracle.toplink.essentials.exceptions.OptimisticLockException, it's not getting caught? Even though the name of exception-class is the same, they're not the same class.

1
Ralph On

I would guess that it is thrown in the em.getTransaction().commit(); statement.

Because the java doc of RollbackException if said:

Thrown by the persistence provider when EntityTransaction.commit() fails.

I strongly belive that this is not the code you realy use (it would not compile because of a missing ) in line bean.setVersion(Integer.parseInt(12345);), but i "hope" that the real code has the same problem.

0
NBW On

Have you tried calling entityManager.flush(); inside your try/catch block? When JPA flushes is when the OptimisticLock exception is thrown.

Also you need not commit the transaction in the manner you did. You simply could have done txn.commit(); instead of em.getTransaction().commit();.

I have a similar situation where I am able to catch javax.persistence.OptimisticLockException. In my case I made the ReST endpoint a SSB and inject the entity manager. I then call a method on another SSB which is also injected and acts as a controller for this piece of biz logic. This controller performs a flush() and catches the OLEX and rethrows and ApplicationException which the Rest endpoint / SSB catches and retries. Using this pattern you also need to make sure to specify TransactionAttributeType.RequiresNew so that each retry you make occurs in a fresh transaction since the OLEX invalidates the old one.