jeudi 18 juin 2015

Handle OptimisticLock Exception and edit field in the database

I'm handling concurrency updates in to MySQL database. I'm using OptimisticLock.

Let's say I've table Job and table Person. I'm using OptimisticLock on the Job table. When an OptimisticLockException occurs I still want to update a field in the Person table but I'm not capable of doing so because the transaction as been marked for rollback (TransactionRolledbackLocalException).

Here's my code:

public Operation accept(Person person, long jobId) throws LockedRowException {

       (...)

       job.setPersonSelectedCardId(person.getSelectedCardId());         
       job.setLastEventDate(currentTime);         
       job.setStatus(OperationStatus.ACCEPTED.getStatus());         

       try {         
           // Update job with optimistic lock         
           jobDAO.editWithOptimisticLock(job);         
       } catch (LockedRowException ex) {         
           // Here I want to update the person table but
           // it is not updating it because the transaction 
           // is marked to be rolled back      
           setPersonNrAcceptedJobsAndUpdateScore(person);         
           throw new LockedRowException(ex);         
       }         
       (...)
}

In the catch clause I want to update a person in the Person table. So my question is, how can I update the Person table when the transaction has been marked for rollback from an OptimisticLock caused in the Job table?

I'm using JavaEE with JPA and MySQL on Glassfish.

EDIT:

This is for a RESTful server. I still need to throw an exception inside the catch to notify my endpoint that will notify the user with a CONFLICT response. So I need to throw an exception to the upper level.

EDIT2:

My LockedRowException is a custom exception that is throw on my Abstract class that implements the JPA edit/merge/flush methods:

public class LockedRowException extends Exception {

    private final OptimisticLockException optimisticLockException;
    private final Exception exception;

    public LockedRowException(OptimisticLockException optimisticLockException) {
        super("Locked Transaction Exception - Entity was locked.");
        this.optimisticLockException = optimisticLockException;
        this.exception = null;
    }

    public LockedRowException(Exception exception) {
        super("Locked Transaction Exception - Entity was locked.");
        this.optimisticLockException = null;
        this.exception = exception;
    }

    public LockedRowException(OptimisticLockException optimisticLockException, Exception exception) {
        super("Locked Transaction Exception - Entity was locked.");
        this.optimisticLockException = optimisticLockException;
        this.exception = exception;
    }

    public OptimisticLockException getOptimisticLockException() {
        return optimisticLockException;
    }
}

Here's my edit method in my abstract class:

public void editWithOptimisticLock(T entity) throws LockedRowException {        
        getEntityManager().lock(entity, LockModeType.WRITE);

        try {
            mergeAndFlush(entity);
        }
        catch(org.eclipse.persistence.exceptions.OptimisticLockException ex) {
            logger.warn("Concurrency detected - Entity: {}", entity.getClass().getSimpleName());
            throw new LockedRowException(new OptimisticLockException(entity));
        }
        catch(OptimisticLockException ex) {
            logger.warn("Concurrency detected - Entity: {}", entity.getClass().getSimpleName());
            throw new LockedRowException(new OptimisticLockException(entity));
        }
        catch(RuntimeException re) {
            logger.warn("Concurrency detected - Entity: {}", entity.getClass().getSimpleName());
            throw new LockedRowException(new OptimisticLockException(entity));
        }
    }

Aucun commentaire:

Enregistrer un commentaire