In Spring Boot 3.0.0, ZipkinConfigurations.RestTemplateSenderConfiguration create a RestTemplate by relying on RestTemplateBuilder.
The contract indicates that providing a ZipkinRestTemplateBuilderCustomizer would allow for customization of the generated RestTemplate.
However, RestTemplateBuilder is immutable and each method returns a new instance (contrary to the WebClient version).
As a consequence, customization is impossible.
Example failing test:
@Test
void should_apply_interceptors() {
ClientHttpRequestInterceptor interceptor1 = mock(ClientHttpRequestInterceptor.class);
ZipkinRestTemplateBuilderCustomizer customizer = builder -> builder.additionalInterceptors(interceptor1);
RestTemplate restTemplate = restTemplateSender(new ZipkinProperties(), new TestObjectProvider<>(customizer));
// empty list
assertThat(restTemplate.getInterceptors()).singleElement().isEqualTo(interceptor1);
}
// copied from org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConfigurations.RestTemplateSenderConfiguration#restTemplateSender
RestTemplate restTemplateSender(ZipkinProperties properties,
ObjectProvider<ZipkinRestTemplateBuilderCustomizer> customizers) {
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder()
.setConnectTimeout(properties.getConnectTimeout()).setReadTimeout(properties.getReadTimeout());
customizers.orderedStream().forEach((customizer) -> customizer.customize(restTemplateBuilder));
return restTemplateBuilder.build();
}
@RequiredArgsConstructor
static class TestObjectProvider<T> implements ObjectProvider<T> {
private final T t;
@Override
public T getObject(Object... args) throws BeansException {
return t;
}
@Override
public T getIfAvailable() throws BeansException {
return t;
}
@Override
public T getIfUnique() throws BeansException {
return t;
}
@Override
public T getObject() throws BeansException {
return t;
}
@Override
public Stream<T> orderedStream() {
return Stream.of(t);
}
}
I think that it is required to make ZipkinRestTemplateBuilderCustomizer return a RestTemplateBuilder to have a working solution, or mutate the RestTemplate instead of the RestTemplateBuilder.
Work-around:
- Define your own
ZipkinRestTemplateSender(which requires duplicating a lot of classes since ZipkinRestTemplateSender is package private) - Use the web client version, which should not have this problem.
Comment From: wilkinsona
I think we should change the signature of the customize method from void customize(RestTemplateBuilder restTemplateBuilder) to RestTemplateBuilder customize(RestTemplateBuilder restTemplateBuilder). While it is technically a breaking change, I think it's OK as the method's useless in its current form.
Comment From: wilkinsona
We discussed this today and decided to change customize to return RestTemplateBuilder.