After upgrading from Hoxton SR9 to Hoxton SR10 we suddenly get the following error during startup:
No bean found of type interface org.springframework.cloud.openfeign.Targeter
I must add that we have always excluded feign-hystrix in the past because we did not use it and the dependency is rather "heavy".
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hystrix</artifactId>
</exclusion>
</exclusions>
</dependency>
FeignAutoConfiguration supported this before Hoxton SR10 by conditionally loading the DefaultTargeter instead of the HystrixTargeter:
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
But as of Hoxton SR10, Spring Cloud Circuit Breaker support was added to FeignAutoConfiguration and the conditionals have changed.
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass({ "feign.hystrix.HystrixFeign",
"org.springframework.cloud.client.circuitbreaker.CircuitBreaker" })
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
Now the DefaultFeignTargeterConfiguration is only loaded if both HystrixFeign and CircuitBreaker interface are not on the classpath. The CircuitBreaker interface however is always included through spring-cloud-commons and thus the DefaultFeignTargeterConfiguration condition will never load.
Plus, the newly added CircuitBreakerPresentFeignTargeterConfiguration also tries to register a DefaultTargeter in case:
CircuitBreakeris on the classpath (always true)feign.circuitbreaker.enabledis set to true (which defaults to false).- There is no
CircuitBreakerFactorybean defined
This however feels strange as one would have to set feign.circuitbreaker.enabled to true without actually using circuit breaking just to get the DefaultTargeter to load.
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CircuitBreaker.class)
@ConditionalOnProperty("feign.circuitbreaker.enabled")
protected static class CircuitBreakerPresentFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean(CircuitBreakerFactory.class)
public Targeter defaultFeignTargeter() {
return new DefaultTargeter();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(CircuitBreakerFactory.class)
public Targeter circuitBreakerFeignTargeter(CircuitBreakerFactory circuitBreakerFactory) {
return new FeignCircuitBreakerTargeter(circuitBreakerFactory);
}
}
In its current state, I have the feeling that the DefaultFeignTargeterConfiguration is unreachable code and that it would be better to merge the 2 DefaultTargeter definitions into one Configuration that is conditionally loaded when both Hystrix or Spring Cloud Circuit Breaker are not explicitly enabled.
I'll be happy to submit a pull request if you can provide some feedback/guidance on this.
Comment From: OlgaMaciaszek
@timpeeters Thanks for reporting this. It's, in fact, a bug. We will welcome a pull request.
I agree that we should instantiate the DefaultTargeter if either the FeignCircuitBreakerTargeter or the HystrixTargeter is not being instantiated, however, we should verify for both the property and the class (the property is from Spring Cloud OpenFeign, so it's possible that the user sets the property to true, but there's no class present) in both cases.
Please submit the PR against the 2.2.x branch.