Background
This started off when my colleague asked me why, when defined with our own RestTemplate Bean
, there is no need to use @Qualifier
to injecting the bean into the class.
Imagine the following code
@Configuration
public class WebConfig {
@Bean
public RestTemplate myRestTemplate() {
return new RestTemplate();
}
}
@Service
@RequiredArgsConstructor
public class PokemonAPI {
// @Qualifier("myRestTemplate") -- not required
private final RestTemplate restTemplate;
}
- We declared a
RestTemplate
bean inWebConfig
class, with name asmyRestTemplate
- We injected the
RestTemplate
intoPokemonAPI
class without using@Qualifier
I stumbled for a while, and I couldn't think any reasonable answer at that time. Why is that so?
Assumption
My initial assumption was actually the cause of the misunderstanding. Since we are dealing with Spring Boot
, I automatically assume that a default auto-configured RestTemplate
bean must have been provided. Hence, if I also initialize my own RestTemplate
as shown above, there would have been 2 different RestTemplate
bean. I couldn't have been more wrong.
Thinking back, even if that is the case, there wouldn't have been 2 different beans because Spring Boot is known to backoff when there is a bean defined manually. Therefore, there should only have a single bean even if we declared RestTemplate
bean in the WebConfig
class.
This is a sign of rusty knowledge of core Spring / Spring Boot.
Finding Answers
Determined to search for the answer, I wrote some code and attempt to find out why. I know that this is something basic, but I just couldn't figure out at that point of time.
I had this code
@Configuration
public class WebConfig {
@Bean
public RestTemplate myRestTemplate() {
return new RestTemplate();
}
}
@RequiredArgsConstructor
public class PokemonAPI {
private static final String POKE_URL = "https://pokeapi.co/api/v2/pokemon/{name}";
private final RestTemplate restTemplate;
public Pokemon get(String name) {
return restTemplate.exchange(POKE_URL, HttpMethod.GET, null, Pokemon.class, name).getBody();
}
}
And I never once thought to not configure a self defined RestTemplate
bean to test it out for some reason.
Auto Backoff
As mentioned previously, I should have thought of this point earlier because this might give me a hint earlier to look elsewhere. At the back of my mind, I am convinced that there should have 2 beans, so why the heck @Qualifier
is not required?
No auto-configured RestTemplate
Unable to figure out, I turned to Twitter and Stéphane Nicoll was kind enough to point me to the docs, and that's when I know (I never knew this before) Spring does not provide auto-configured RestTemplate
bean which, as mentioned, was the basis of my assumption initially.
Once again, this proves that we should always look at the official doc first. RTFM anyone?
Since RestTemplate instances often need to be customized before being used, Spring Boot does not provide any single auto-configured RestTemplate bean
Conclusion
Since there is only a single instance of RestTemplate
bean configured, naturally, there is no need for @Qualifier
and Spring can inject RestTemplate
just fine using byType autowiring. And always RTFM first!
Tips
This is not the focus of this post but I thought I should mentioned this, as far as possible, we should use RestTemplateBuilder
to initialize RestTemplate
instance which is also mentioned in the docs
It does, however, auto-configure a RestTemplateBuilder, which can be used to create RestTemplate instances when needed. The auto-configured RestTemplateBuilder ensures that sensible HttpMessageConverters are applied to RestTemplate instances.
Source Code
Full source code is available in GitHub