Spring Retry Transaction

Is Spring Retry a guarantee of working with Spring @Transactional annotation?

In particular, I'm trying to use @Retryable for optimistic locking. It looks like this will depend on the ordering of the AOP proxies that were created. For example, if the calls are as follows:

Calling code → Retry Proxy → Proxy Proxy → Actual DB code

Then it will work correctly, but if the proxies were structured as follows:

Calling code → Proxy Proxy → Retry Proxy → Actual DB code

Then the replay will not work, because the act of closing a transaction is what the optmistic lock exception throws.

When testing, it seems to have generated the first case (try again, then the transaction), but I could not say if this was guaranteed behavior or just lucky.

+6
source share
3 answers

Found the answer here: https://docs.spring.io/spring/docs/5.0.6.BUILD-SNAPSHOT/spring-framework-reference/data-access.html#transaction-declarative-annotations Table 2 indicates that the advice for an annotation, Transactional is of the order Ordered.LOWEST_PRECEDENCE , which means that it is safe to combine Retryable with Transactional if you do not redefine the order of recommendations for these 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 } 
+1
source

If you want to test it for independence and be sure how it behaves, then you can have @Transactional @Service, then another service that uses the transaction alone and simply adds the iterations.

In this case, no matter how you test, you rely on undocumented behavior (how exactly annotation processing is ordered). This may change between minor releases based on the order in which independent Spring beans are created, etc. In other words, you are having trouble mixing @Transactional and @Retry with the same method.

edit: there is a similar answer to the question fooobar.com/questions/339934 / ... with code

 @Retryable(StaleStateException.class) @Transactional public void doSomethingWithFoo(Long fooId){ // read your entity again before changes! Foo foo = fooRepository.findOne(fooId); foo.setStatus(REJECTED) // <- sample foo modification } // commit on method end 

In this case, everything seems to be in order, because no matter what order (try again, transaction or transaction, or try again), the observed behavior will be the same.

+1
source

By default, Spring Retry builds a tip with the same LOWEST_PRECEDENCE order - take a look at RetryConfiguration. However, there is a fairly simple way to override this order:

 @Configuration public class MyRetryConfiguration extends RetryConfiguration { @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } } 

Be sure to omit the @EnableRetry annotation to avoid taking into account the default RetryConfiguration.

0
source

Source: https://habr.com/ru/post/1276271/


All Articles