Reputation: 2147
how are you? I hope you are doing awesome.
I'm creating a new Spring Boot app for my company and for this specific app I need to communicate with different micro-services, some with different configurations. For example: Some services require different headers.
Im not quite sure how to do it in a correct elegant way. I was taking the approach to create "Clients" as @Component that communicate with the micro-services using a rest template created like this:
@Component
public class ShifuClient {
private final RestTemplate restTemplate;
private static final String HOST = "http://example.com/service/";
@Autowired
public ShifuClient(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
public ShifuDto getShifuTemplate(Locale locale) {
return this.restTemplate.getForObject(HOST+ "?locale={locale}", ShifuDto.class, locale.toString());
}
}
I also have a bean for an application wide customizer that adds common headers and logs the request.
/**
* Customizes the creation of the {@link RestTemplate}
* used for connecting with other services.
* This configuration is application wide and applies to every request made with {@link RestTemplate}.
*/
public class ApplicationWideRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
restTemplate.getInterceptors().add(new AddHeadersRequestInterceptor());
restTemplate.getInterceptors().add(new LogRequestInterceptor());
}
}
So the problem is now that I want a specific header configuration + the common header configuration for the resttemplate of different clients. I can also see that a pattern will repeat, maybe I will need an abstract "Client" class.
How do you think I must proceed in the design to make this elegant and to make this work as intended?
Thank you very much for your help.
Upvotes: 2
Views: 4818
Reputation: 8729
I think you're almost there. First of all, take a look at the RestTemplateBuilder
which you're using above. You probably want to "build" clients out based on your common template.
In your configuration, make your common template Builder
:
@Configuration
public RestClientConfig {
private static final String HOST = "http://example.com/service/";
// Here you can define a common builder for all of your RestTemplates
@Bean
public RestTemplateBuilder restTemplateBuilder() {
// Here you're appending the interceptors to the common template
return new RestTemplateBuilder().addAdditionalInterceptors(
new AddHeadersRequestInterceptor(),
new LogRequestInterceptor()
).rootUri(HOST);
}
@Bean
public RestTemplate shifuRestTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.addAdditionalInterceptors(new CustomShifuHeaderIntercepter()
// Add other Customizers or MessageConverters here with #additionalCustomizers and #additionalMessageConverters...
.build();
}
public RestTemplate foobarRestTemplate(RestTemplateBuilder restTemplateBuilder) {
...
}
}
And then inject those as needed into your @Services/@Components
. You can still use your Client
service idea here, but you can inject the Templates you've configured. Hope that helps.
Upvotes: 4