I not able to perform DB operations in a transaction if I add @Retryable
from spring-retry library. This is how my code structure looks like:
public class ExpireAndSaveTrades {
@Transactional(rollbackFor = MyException.class)
public void expireAndSaveTrades(List<Trade> trades) {
try {
// these two MUST be executed in one transaction
trades.forEach(trade -> dao.expireTrades(trade));
dao.saveTrades(trades);
} catch (Exception e) {
throw new MyException(e.getMessage(), e);
}
}
}
public class Dao {
@Retryable(value = CannotAcquireLockException.class,
maxAttempts = 3,
stateful = true,
backoff = @Backoff(delay = 300, multiplier = 3))
public void expireTrades(Trade trade) {
try {
tradeRepository.expire(trade.getId(), trade.getNewStopDate());
} catch (CannotAcquireLockException e) {
expireTrade(trade);
}
}
@Retryable(value = CannotAcquireLockException.class,
maxAttempts = 3,
stateful = true,
backoff = @Backoff(delay = 300, multiplier = 3))
public void saveTrades(List<Trades> trades) {
try {
tradeRepository.saveAll(trades)
} catch (CannotAcquireLockException e) {
saveTrades(trades);
}
}
}
public interface TradeRepository extends JpaRepository<Trade, Integer> {
@Modifying
@Query(value = "update trade set stop_date=:new_stop_date where id=:id", nativeQuery = true)
void expire(@Param("id") int id, @Param("new_stop_date") String newStopDate);
}
So there is where I am right now:
- Without using stateful (i.e. stateful is set to
false
by default) - retry happens successfully but then at the end of it, I see this exception:org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
and the data which was updated/saved after multiple retries is rolled back in the database table - stateful = true - retry doesn't happen anymore
I have gone through many SO posts and blogs but couldn't find the solution to my problem. Can anybody here please help me out ?
EDIT: updated my question to add try-catch block With this the spring-retry doesn't kick in ( I know because I added a listener to @Retryable
to log the retryContext
. I dont see the log getting printed. Also the transaction silently rolls back if there was a CannotAcquireLockException
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
LOGGER.info("Retry Context - {}", context);
}