I have a @Retryable
placed at the class level.
@Import({GrpcClientRetryConfig.class})
@Retryable(interceptor = "grpcClientRetryInterceptor")
@Component
public class Profile {
public void method1() {
method2();
}
public void method2() {
val msg = "Hello World";
System.out.println(msg);
throw new RunTimeException("Testing");
}
}
@EnableRetry
@Configuration
public class GrpcClientRetryConfig {
@Bean
public RetryOperationsInterceptor grpcClientRetryInterceptor() {
val template = new RetryTemplate();
val backOffPolicy = new ExponentialBackOffPolicy();
// Set the exponential backoff parameter
val interceptor = new RetryOperationsInterceptor();
val simpleRetry = new SimpleRetryPolicy();
simpleRetry.setMaxAttempts(2);
template.setRetryPolicy(simpleRetry);
template.setBackOffPolicy(backOffPolicy);
template.setListeners(new GrpcClientRetryListener[] {new GrpcClientRetryListener()});
interceptor.setRetryOperations(template);
return interceptor;
}
}
Case 1
val profile = new Profile();
profile.method2(); // Hello World printed twice an exception is thrown
Case 2
val profile = new Profile();
profile.method1(); // Hello World printed twice and then an exception is thrown
A sample project is placed here. Please check com.example.helloworld.controller.HelloWorldController#sendGreetings
Should not Hello World
be printed 4 times? method1()
calls method2()
. method2()
gets retried 2 times and then throws the exception to method1()
which again calls method2()
one more time?
Can someone let me know why method1()
is not retried twice in the second case? How does spring determine which methods to be retried when a @Retryable
is placed at the class level?
I cannot reproduce it. Works as expected:
@Bean
ApplicationRunner applicationRunner(ServiceWithRetry serviceWithRetry) {
return args -> {
System.out.println("Test method2");
try {
serviceWithRetry.method2();
}
catch (Exception e) {
}
System.out.println("Test method1");
try {
serviceWithRetry.method1();
}
catch (Exception e) {
}
};
}
and the output:
Test method2
2024-04-01T14:40:57.956-04:00 TRACE 34592 --- [ main] o.s.retry.support.RetryTemplate : RetryContext retrieved: [RetryContext: count=0, lastException=null, exhausted=false]
2024-04-01T14:40:57.956-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=0
Method2
2024-04-01T14:40:57.957-04:00 DEBUG 34592 --- [ main] o.s.r.backoff.ExponentialBackOffPolicy : Sleeping for 100
2024-04-01T14:40:58.068-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=1
2024-04-01T14:40:58.068-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=1
Method2
2024-04-01T14:40:58.069-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=2
2024-04-01T14:40:58.069-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry failed last attempt: count=2
Test method1
2024-04-01T14:40:58.069-04:00 TRACE 34592 --- [ main] o.s.retry.support.RetryTemplate : RetryContext retrieved: [RetryContext: count=0, lastException=null, exhausted=false]
2024-04-01T14:40:58.069-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=0
Method1
Method2
2024-04-01T14:40:58.070-04:00 DEBUG 34592 --- [ main] o.s.r.backoff.ExponentialBackOffPolicy : Sleeping for 100
2024-04-01T14:40:58.176-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=1
2024-04-01T14:40:58.176-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=1
Method1
Method2
2024-04-01T14:40:58.176-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=2
2024-04-01T14:40:58.176-04:00 DEBUG 34592 --- [ main] o.s.retry.support.RetryTemplate : Retry failed last attempt: count=2
Any chances that you can share a simple Spring Boot project we can play with?
UPDATE
Thank you for the sample!
I have modified your method1
like:
public String method1() {
System.out.println("method1");
return method2();
}
and added this property:
logging.level.org.springframework.retry=debug
After running HelloWorldControllerTest
I got this output:
2024-04-02T11:03:31.347-04:00 DEBUG 20888 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=0
method1
Hello World
2024-04-02T11:03:31.348-04:00 DEBUG 20888 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=1
2024-04-02T11:03:31.348-04:00 DEBUG 20888 --- [ main] o.s.retry.support.RetryTemplate : Retry: count=1
method1
Hello World
2024-04-02T11:03:31.348-04:00 DEBUG 20888 --- [ main] o.s.retry.support.RetryTemplate : Checking for rethrow: count=2
2024-04-02T11:03:31.348-04:00 DEBUG 20888 --- [ main] o.s.retry.support.RetryTemplate : Retry failed last attempt: count=2
So, works as expected.
The retry advice is applied on this method1()
and calling that method2()
from here does not cause the second, nested retry to be initiated.