Guido Celada
Guido Celada

Reputation: 2147

What is the correct achitecture using RestTemplate and RestTemplateCustomizer with multiple services?

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

Answers (1)

Dovmo
Dovmo

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

Related Questions