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.