'Spring Retry: How to make all methods of a @Bean retryable?
I would like to create a @Bean
of a third party service like Keycloak (or any other) which may or may not be reachable at any given time. This object should retry all methods of the resulting Keycloak
bean.
I have tried the following:
@Configuration
@EnableRetry
class KeycloakBeanProvider() {
@Bean
@Retryable
fun keycloak(oauth2ClientRegistration: ClientRegistration): Keycloak {
return KeycloakBuilder.builder()
.serverUrl(serverUrl)
.realm(oauth2ClientRegistration.clientName)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(oauth2ClientRegistration.clientId)
.clientSecret(oauth2ClientRegistration.clientSecret)
.build()
}
}
But this way only the bean creation will be retried, not actual method calls on the bean. I know @Retryable
can be used on class level but I don't own the Keycloak
class so I can't add it there.
How can I make the methods of the resulting Keycloak
bean retryable?
Solution 1:[1]
You have to annotate the Keycloak
with @Retryable
.
@SpringBootApplication
@EnableRetry
public class So70593939Application {
public static void main(String[] args) {
SpringApplication.run(So70593939Application.class, args);
}
@Bean
ApplicationRunner runner(Foo foo) {
return args -> {
foo.foo("called foo");
foo.bar("called bar");
};
}
}
@Component
@Retryable
class Foo {
public void foo(String in) {
System.out.println("foo");
throw new RuntimeException("test");
}
public void bar(String in) {
System.out.println("bar");
throw new RuntimeException("test");
}
@Recover
public void recover(Exception ex, String in) {
System.out.println(ex.getMessage() + ":" + in);
}
}
foo
foo
foo
test:called foo
bar
bar
bar
test:called bar
If you can't annotate the class (e.g. because it's from another project), you need to use a RetryTemplate
to call its methods instead of using annotation-based retry.
Solution 2:[2]
You can manually instrument your class. Check documentation.
@Bean
public Keycloak myService() {
ProxyFactory factory = new ProxyFactory(RepeatOperations.class.getClassLoader());
factory.setInterfaces(Keycloak.class);
factory.setTarget(createKeycloak());
Keycloak keycloak = (Keycloak) factory.getProxy();
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns(".*.*");
RetryOperationsInterceptor interceptor = new RetryOperationsInterceptor();
((Advised) keycloak).addAdvisor(new DefaultPointcutAdvisor(pointcut, interceptor));
return keycloak;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Gary Russell |
Solution 2 | Juan Rada |