I have a method that is annotated with
@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
and calls several repository methods. Now when one repository tries to alter a DB-row that is locked and not rolled back by another instance of the method, spring correctly throws
org.springframework.orm.jpa.JpaSystemException: could not execute statement [...] Caused by: java.sql.SQLException: transaction could not be serialized and rolls back the failed transaction.
Now I want to keep all this behaviour but additionally handle the exception and start a retry. Here's a code snippet:
@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Lock(LockModeType.PESSIMISTIC_WRITE)
public void messageReceived(Card card) {
this.request = request;
this.numberOfAttempts = reset ? 0 : this.numberOfAttempts++;
this.reset = true;
LOGGER.info("Message received from Queue: " + card);
TransactionDebugUtils.transactionRequired("MessageReceivedController.messageReceived");
try {
[...]
repository1.createKonto(card);
repository2.doStuff(card);
} catch (JpaSystemException e) {
//This is obviously never invoked
LOGGER.error("TRANSACTION FAILED!!!");
} catch (Exception e) {
LOGGER.error("Error mapping json request to data model", message, e);
}
}
@ExceptionHandler(JpaSystemException.class)
//This is also never invoked
public void handleJpaSystemException(JpaSystemException ex) {
this.messageReceived(this.request);
this.reset = false;
}
I had this issue recently. As it is a method level @Transactional annotation, Transaction commit occurs after finishing method execution. When you are using this annotation 2 concepts should be considered
After messageReceived() method is executed, those 2 things will happen and JPA exception is thrown at @Transactional level which means you need to handle this exception from where you are calling this method(controller; if you are calling from a controller). More regarding @Transactional can be found in this link.