REST, Spring, Spring Boot

Using multiple RetsTemplates in Spring Boot application

Recently I had to request information from my Spring Boot application from multiple services via REST. Normally it works so simple as calling a the service URL, like this:

ResponseEntity response = restTemplate.getForEntity(url, MyResponse.class);

 

Although in my case both services required different authentication method. The first one was an open service, the second one required basic authentication. At the beginning, I thought, It will be so easy, as adding the basic authentication feature to the RestTemplate, and the first service will simply ignore it. But it turned out, that this solution does not work. The service without any authentication responded HTTP 401, also authentication problem, when it received the request with basic authentication data.

Therefore I had to implement a Spring configuration class and create two beans with type RestTemplate. My configuration class looked like this:

@Configuration
public class ApplicationConfiguration {

  private final String internalServicesUser;
  private final String internalServicesPw;

  public ApplicationConfiguration(Environment env) {
    this.internalServicesUser = env.getRequiredProperty("internal-services.user");
    this.internalServicesPw = env.getRequiredProperty("internal-services.password");
  }

  @Bean("restTemplateForInternalServiceCalls")
  public RestTemplate restTemplateForInternalServiceCalls(@Autowired RestTemplateBuilder builder) {
    return builder
        .setConnectTimeout(Duration.ofSeconds(5))
        .setReadTimeout(Duration.ofSeconds(5))
        .basicAuthentication(internalServicesUser, internalServicesPw)
        .build();
  }

  @Bean
  public RestTemplate restTemplate(@Autowired RestTemplateBuilder builder) {
    return builder
        .setConnectTimeout(Duration.ofSeconds(5))
        .setReadTimeout(Duration.ofSeconds(5))
        .build();
  }
}

 

As the both beans has the same type, a qualifier needed to be defined for one of them, in order for make it possible for the Spring framework to inject the right one in the corresponding components. According to the Spring documentation, the name of the first bean is “restTemplateForInternalServiceCalls”, as defined in the @Bean annotation. The name of the second bean gets generated by the framework based on the method name. Also it is simply called “restTemplate”.

Injecting the RestTemplate instance with authentication to a service works like this: 

@Service
public class ClientWithAuthentication {

  private final String serviceUrl;
  private final RestTemplate restTemplate;

  public ClientWithAuthentication(Environment env,
      @Qualifier("restTemplateForInternalServiceCalls") RestTemplate restTemplate) {
    this.serviceUrl = env.getRequiredProperty("service.url");
    this.restTemplate = restTemplate;
  }
...
}

 

As you can see, the @Qualifier annotation is used as hint for Spring, which bean instance needs to be used.

When it comes to using the one without authentication, the bean with name “restTemplate” gets inserted, as no qualifier is specified. So Spring tries to find the matching bean based on the parameter name.

@Service
public class ClientWithoutAuthentication {

  private final RestTemplate restTemplate;
  private final String serviceUrl;

  // Injecting RestTemplate instance without authentication
  public ClientWithoutAuthentication(Environment env, RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
    this.serviceUrl = env.getRequiredProperty("myservice.url");
  }
  
  ...
} 

 

Obviously it would also be possible to define a name for the second bean, and use the @Qualifier by injecting it, as it would make the relation more visible. I just wanted to show, that with intelligent defaults from Spring, it is not necessary.

Advertisement