I'm trying to manually create a circuit-breaker-wrapped Feign client, so that I can use callbacks.
I understand that there's another approach that kind of simplify this, which is using the @FeignClient
annotation, as well as enabling fallbacks with feign.circuitbreaker.enabled=true
and importing the spring-cloud-starter-circuitbreaker-resilience4j
dependency. Unfortunately this does not solve our problem, we need to manually create them (with code).
Below is how I'm creating a simple Feign client:
@Bean
public SomeClient client() {
Request.Options options = new Request.Options(1000L, TimeUnit.MILLISECONDS, 3000L, TimeUnit.MILLISECONDS, false);
return Feign.builder()
.options(options)
.contract(new SpringMvcContract())
.target(SomeClient.class, "some_url");
}
Looking at the Spring's FeignClientsConfiguration
class, I found the piece of code responsible of enabling the circuit breaker, which is:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ CircuitBreaker.class })
@ConditionalOnProperty({ "feign.circuitbreaker.enabled" })
protected static class CircuitBreakerPresentFeignBuilderConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnMissingBean({ Builder.class, CircuitBreakerFactory.class })
public Builder defaultFeignBuilder(Retryer retryer) {
return Feign.builder().retryer(retryer);
}
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnBean({ CircuitBreakerFactory.class })
public Builder circuitBreakerFeignBuilder() {
return FeignCircuitBreaker.builder();
}
}
After that, I tried changing from Feign.builder()
to FeignCircuitBreaker.builder()
within our client
bean method, as it supports the T target(Target<T> target, T fallback)
method, although no luck on that: some weird null pointer exception at org.springframework.cloud.openfeign.FeignCircuitBreakerInvocationHandler.invoke(FeignCircuitBreakerInvocationHandler.java:88)
.
Looking at the FeignClientsConfiguration
class again, the circuitBreakerFeignBuilder
method depends on the CircuitBreakerFactory
bean, which is supposedly not being created automatically, so I tried creating one, but this just gets things even more complicated.
I couldn't find much information regarding this issue on the internet, hopefully someone knows how to solve this.