0

Below is my requirement

begin trans
insertData();
updateData();
end trans

Also lets say insertDta method throws some error then I need to retry 5 times .Same with updateData().I should not retry both the methods at the same time i.e if i retry m2() 5 times them m1() should not be retried. Is below the correct way to do it? I call m3() from another class . My concern is that interceptors are added in correct and deterministic order.

@Repository
DaoA
{
    void insertData();
}

@Repository
DaoB
{
    void updateData();
}

Below is my Service class .

@Service
ServiceA 
{
    
    @Retryable(  maxAttempts = 5)
     public void m1 ()
     {
         
         daoA.insertData();
         
     }
    
    
     @Retryable(  maxAttempts = 5)
     public void m2 ()
     {
          daoB.updateData();
     }
    
    

    @Transactional
     public void m3 ()
     {
         
    
          m1();
          m2();
     }
    
hello world
  • 171
  • 3
  • 13

2 Answers2

0

m3() needs to be in a different bean - calling m1() and m2() directly within the class bypasses the proxy and they won't be retried.

In any case, the transaction should be within the retry logic, not the other way around; you need to start a new transaction for each attempt.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Russel .Supose m1() works fine and m2 fails and then i retry m3() 3 times .Then won't m1 insert the same row 3 times?.How can i achieve transaction withing retry logic for my particular scenario – hello world Oct 04 '21 at 15:53
  • @Gary I don't think calling `m1()` and `m2()` within the same class have any effect on `@Retryable`. – ray Oct 04 '21 at 15:53
  • @Gary And i was able to retry m1() 5 times with my code (which i have posted) – hello world Oct 04 '21 at 15:55
  • It will work if you call it from some other bean, not from `m3()` - typically you will nest the transaction inside of retry; that way if one of m1, m2 fail, the other one will roll back and the next retry will start a new transaction and call both methods again. – Gary Russell Oct 04 '21 at 16:04
0

If I got your requirement right, this should work for you.

@Service
ServiceA {
    
    public void m1 () {
         daoA.insertData();
     }
    
    public void m2 () {
          daoB.updateData();
    }

    @Transactional
    @Retryable(value = {Exception.class}, maxAttempts = 5)
    public void m3 () {
          m1();
          m2();
    }
}

This will make sure the total number of retries is maxAttempts = 5.

ray
  • 1,512
  • 4
  • 11
  • yes but we should not use ` @Transactional` and `@Retryable` on same method – hello world Oct 05 '21 at 08:54
  • @helloworld why is that? – ray Oct 05 '21 at 09:57
  • Read this https://stackoverflow.com/questions/69034571/spring-retry-with-transactional-annotation Gary Russel is the developer for Spring-retry project – hello world Oct 05 '21 at 10:16
  • @helloworld I think what he is trying to say is Its better to do it that way, but this way also works. Anyway you issue is now resolved. That's what matters. Cheers! – ray Oct 05 '21 at 12:03
  • correct.following his way makes it deterministic and always behave in the same way – hello world Oct 05 '21 at 13:22