I am having troubles often with restTemplates and autconfigurations, both at private projects and spring ones. Thus lead me to wonder if there should be a mechanism like forcing a bean to be qualified in a certain way, for instance:
XAutoconfiguration:
@ConditionalOnMissingQualifiedBean(value = RestTemplate.class, qualifier = "X")
@Bean @Qualifier("X")
public RestTemplate YRestTemplate(RestTemplateBuilder rtb){
return rtb.restTemplate(); //With custom config expected for this starter
}
YAutoconfiguration:
@ConditionalOnMissingQualifiedBean(value = RestTemplate.class, qualifier = "Y")
@Bean @Qualifier("Y")
public RestTemplate YRestTemplate(RestTemplateBuilder rtb){
return rtb.restTemplate(); //With custom config expected for this starter
}
That would solve 2 problems:
- We wouldn't require having to sacrifice our @Primary
restTemplate design in our apps to take profit of classes like : https://github.com/spring-cloud/spring-cloud-dataflow/blob/main/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientAutoConfiguration.java.
- We could expose beans on our particular auto-configurations with their purposed pre-configurations without fear of side-effecting the main app, and the other way around, we could accept beans like RestTemplate
in auto-configurations being sure their injection is completely on purpose (for instance the previous auto-configuration example could reconfigure a resttemplate of the app without the user being aware)
- We would just need to make our main app is strict on qualifier as well or either define its main instance as @Primary
, although if all auto-configurations used my design, then the only available RestTemplate
to inject on main app would be only a potential one defined in it (provided there is a way to disable auto-injection of qualified beans on non-qualified @Autowireds
)
Would this be a nice feature? I am assuming there is no similar way to accomplish this that I am unaware of, if so I appreciate if you let me know.
Comment From: philwebb
We've faced similar problems with RestTemplate
in the past and in my opinion the best solution is to not make it a bean. We introduced RestTemplateBuilder
specifically for that purpose. If you really really need to share a RestTemplate
class then I think the better option is to wrap it in another type rather than use qualifiers.
E.g.:
@ConditionalOnMissingQualifiedBean(value = RestTemplate.class, qualifier = "X")
@Bean
public YRestTemplate YRestTemplate(RestTemplateBuilder rtb){
return new YRestTemplate(rtb.restTemplate()); //With custom config expected for this starter
}
@Component
class Something {
Something(YRestTemplate yRestTemplate) {
RestTemplate rt = yRestTemplate.getRestTemplate();
}
}
I think qualifiers add an extra level of complexity to auto-configuration that we shouldn't encourage.
Thanks anyway for the suggestion.
Comment From: nightswimmings
Thanks for your answer, Phil! Although your suggestion would imply that the very Spring classes like https://github.com/spring-cloud/spring-cloud-dataflow/blob/main/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientAutoConfiguration.java should be injecting and expecting a custom wrapper