views:

20

answers:

2

I have a situation with a legacy system which uses JEE Bean Managed Transactions. It's getting LockAcquisitionException thrown when it's trying to retrieve something it just created.

My initial thoughts were this:

@TransactionAttribute(SUPPORTS)
public Item retrieveItem(int id) {
 Item i;
 try {
   i = em.find(Item.class, id);
 } catch (PersistenceException e) {
   if (e.getCause() instanceof LockAcquisitionException) {
     i = retrieveItem(id);
   }
 }
 return i;
}

However - when the recursive call is made, the transaction has already died - and it doesn't seem to create a new one. I've tried different TransactionAttributes, but it doesn't seem to make a difference. Also tried managing the transaction myself (em.getTransaction()), but that's illegal in CMT.

I'm not looking for an elegant fix - as I said, this is legacy, I just need something that will triage it until the whole thing gets replaced in a couple of months!

Cheers.

+1  A: 

Try to annotate retrieveItem with @TransactionAttribute(REQUIRES_NEW): it will then be executed in a new transaction.

Note that:

  1. the the first was has been invalidated (set for rollback) and will never complete
  2. during the second transaction, changes done in the first transaction are not visible anyway

So I don't know if it fits your scenario. But it's the only way I know to do an operation and commit it successfully if the original transaction has been invalidated.

ewernli
Thanks.. tried that but it still isn't working.. I'm not entirely sure it's picking up the annotations, as I get a 'Transaction not active' error. :(
Robert Wilson
@Robert Wilson My mistake, I overlooked the fact that you use BMT. Could you try to inject the `UserTransaction` and use it to start/stop a new one, instead of `em.getTransaction` ?
ewernli
A: 

Unfortunately the only way I can find to do this is to fix the cause of the transaction - so now I'm doing a em.flush() at the beginning of retrieveItem(). Can't wait to replace this app..

Robert Wilson