Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Retry with Transactional

Tags:

Is Spring Retry guaranteed to work with Spring's @Transactional annotation?

Specifically, I'm trying to use @Retryable for optimistic locking. It seems like it would be dependent on the ordering of the AOP proxies that were created. For example, if the calls look like this:

Calling code -> Retry Proxy -> Transaction Proxy -> Actual DB Code

Then it would work correctly, but if the proxies were structured like this:

Calling code -> Transaction Proxy -> Retry Proxy -> Actual DB Code

Then the retry wouldn't work, because the act of closing the transaction is what throws the optmistic locking exception.

In testing, it appeared to generate the first case (retry, then transaction), but I couldn't tell if this was a guaranteed behavior or just lucky.

like image 410
Cobra1117 Avatar asked Apr 05 '18 17:04

Cobra1117


People also ask

How do I retry a Spring boot?

Implementing the Retry Logic. First, you need to enable Spring Retry. You can achieve this by adding the @EnableRetry annotation to your @SpringBootApplication or @Configuration class. You can now use @Retryable to annotate any method to be a candidate or retry and @Recover to specify fallback methods.

What does @transactional do in Spring?

The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.

Does @transactional throw exception?

@Transactional only rolls back transactions for unchecked exceptions. For checked exceptions and their subclasses, it commits data. So although an exception is raised here, because it's a checked exception, Spring ignores it and commits the data to the database, making the system inconsistent.

Does @transactional works on private method?

The answer your question is no - @Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them. When using proxies, you should apply the @Transactional annotation only to methods with public visibility.


1 Answers

Found the answer here: https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html#tx-decl-explained Table 2 indicates that the advice for the Transactional annotation has an order of Ordered.LOWEST_PRECEDENCE, which means that it is safe to combine Retryable with Transactional as long as you aren't overriding the order of the advice for either of those annotations. In other words, you can safely use this form:

@Retryable(StaleStateException.class)
@Transactional
public void performDatabaseActions() {
    //Database updates here that may cause an optimistic locking failure 
    //when the transaction closes
}
like image 105
Cobra1117 Avatar answered Sep 29 '22 05:09

Cobra1117