LoadBalancerAutoConfiguration does not add LoadBalancerInterceptor via org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer when another org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer bean exists
ZIRAKrezovic opened this issue · 6 comments
Due to usage of @ConditionalOnMissingBean
in LoadBalancerAutoConfiguration
, bean
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
will not get published if another @Bean
implementing org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
exists, resulting in RestTemplate
that is annotated with @LoadBalanced
not having the LoadBalancerInterceptor
interceptor registered. This is a consequence when using @ConditionalOnMissingBean
According to the code above,
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
more than one Bean implementing org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
can be present.
Hello @ZIRAKrezovic this interface is provided by the loadbalancer
package, added there specifically for the purpose of setting up load-balancing; we do not really expect the users to create one unless they want to override the behaviour of the one we create. Other than that, I'm not sure why it would be used by the users, since the users create and can customise the RestTemplate
bean itself. Could you provide more information on what your use-case is here?
Hi @OlgaMaciaszek. It seems that I found out why I ran into the problem in the first place.
In short, my use case is "Add some default headers to all RestTemplates produced by AutoConfiguration". BUT: I have implemented the wrong customizer
There are two classes that provide exactly the same behavior
org.springframework.boot.web.client.RestTemplateCustomizer
org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
I was most likely going for the former one while following Spring Web doc, but due to spring cloud being in the class path, the IDE chose the latter one. And it has worked until the changes made in spring-cloud-commons 4.1.1.
Now, it is misleading that the LoadBalancerAutoConfiguration
works with a list of initializers of second type mentioned above when the default implementation backs off. I thought this was a regression.
In any case, I will migrate my code to the Spring Web interface, rather than Spring Cloud Commons one, but you may want to mention this somewhere in the changelog, at least.
Not sure what you mean. We still don't use org.springframework.boot.web.client.RestTemplateCustomizer
there and we have used org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
forever in that class. The only thing that's changed in 4.1.1
is a different customiser introduced that works on RestClient
and not RestTemplate
. The changelog for 4.1.1
: https://github.com/spring-cloud/spring-cloud-commons/releases/tag/v4.1.1.
I meant that I intended to use
org.springframework.boot.web.client.RestTemplateCustomizer
but ended up using
org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
in my code. Still, the problem remains that usage of the latter did not break LoadBalancerInterceptor before.
That @ConditionalOnMissingBean
has been there since 2015
. Not sure why this would change now, but if you provide a sample that reproduces the issue, I can take a look.
Hi @OlgaMaciaszek, you are right. I have tried to create a reproducer https://github.com/ZIRAKrezovic/spring-cloud-reproducer/tree/commons-1335
As soon as I uncomment @Configuration
in https://github.com/ZIRAKrezovic/spring-cloud-reproducer/blob/commons-1335/src/main/java/com/github/krezovic/springcloudreproducer/ProjectRestTemplateCustomizer.java, load balancing breaks and the test fails.
It is possible that it never worked but nobody tested it or that somehow the old post-processor picked it up. But I can't remember defining any RestTemplate.Builder beans that the PostProcessor picked up.
You may close the issue.