Skip to content

Commit 742cb3f

Browse files
committed
Customize RestTemplateBuilder
1 parent 4933b26 commit 742cb3f

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@
3333
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
3434
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.NotReactiveWebApplicationCondition;
3535
import org.springframework.boot.web.client.RestTemplateBuilder;
36+
import org.springframework.boot.web.client.RestTemplateBuilderCustomizer;
3637
import org.springframework.boot.web.client.RestTemplateCustomizer;
3738
import org.springframework.boot.web.client.RestTemplateRequestCustomizer;
3839
import org.springframework.context.annotation.Bean;
3940
import org.springframework.context.annotation.Conditional;
4041
import org.springframework.context.annotation.Configuration;
4142
import org.springframework.context.annotation.Lazy;
43+
import org.springframework.util.Assert;
4244
import org.springframework.web.client.RestTemplate;
4345

4446
/**
@@ -59,6 +61,7 @@ public class RestTemplateAutoConfiguration {
5961
@ConditionalOnMissingBean
6062
public RestTemplateBuilder restTemplateBuilder(ObjectProvider<HttpMessageConverters> messageConverters,
6163
ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers,
64+
ObjectProvider<RestTemplateBuilderCustomizer> restTemplateBuilderCustomizer,
6265
ObjectProvider<RestTemplateRequestCustomizer<?>> restTemplateRequestCustomizers) {
6366
RestTemplateBuilder builder = new RestTemplateBuilder();
6467
HttpMessageConverters converters = messageConverters.getIfUnique();
@@ -67,6 +70,10 @@ public RestTemplateBuilder restTemplateBuilder(ObjectProvider<HttpMessageConvert
6770
}
6871
builder = addCustomizers(builder, restTemplateCustomizers, RestTemplateBuilder::customizers);
6972
builder = addCustomizers(builder, restTemplateRequestCustomizers, RestTemplateBuilder::requestCustomizers);
73+
for (RestTemplateBuilderCustomizer customizer : restTemplateBuilderCustomizer) {
74+
builder = customizer.customize(builder);
75+
Assert.notNull(builder, "RestTemplateBuilderCustomizer returned null builder");
76+
}
7077
return builder;
7178
}
7279

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfigurationTests.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@
2020
import java.util.List;
2121

2222
import org.junit.jupiter.api.Test;
23+
import org.mockito.Mockito;
2324

25+
import org.springframework.beans.factory.BeanCreationException;
2426
import org.springframework.boot.autoconfigure.AutoConfigurations;
2527
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
2628
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
2729
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
2830
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
2931
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
3032
import org.springframework.boot.web.client.RestTemplateBuilder;
33+
import org.springframework.boot.web.client.RestTemplateBuilderCustomizer;
3134
import org.springframework.boot.web.client.RestTemplateCustomizer;
3235
import org.springframework.boot.web.client.RestTemplateRequestCustomizer;
3336
import org.springframework.context.annotation.Bean;
@@ -42,8 +45,10 @@
4245
import org.springframework.web.client.RestTemplate;
4346

4447
import static org.assertj.core.api.Assertions.assertThat;
48+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4549
import static org.mockito.ArgumentMatchers.any;
4650
import static org.mockito.BDDMockito.given;
51+
import static org.mockito.Mockito.doThrow;
4752
import static org.mockito.Mockito.mock;
4853
import static org.mockito.Mockito.verify;
4954

@@ -157,6 +162,28 @@ void whenReactiveWebApplicationRestTemplateBuilderIsNotConfigured() {
157162
.run((context) -> assertThat(context).doesNotHaveBean(RestTemplateBuilder.class));
158163
}
159164

165+
@Test
166+
void customizerShouldCustomizeBuilder() {
167+
contextRunner.withUserConfiguration(RestTemplateBuilderCustomizerConfig.class)
168+
.run((context) -> {
169+
assertThatThrownBy(() -> context.getBean(RestTemplateBuilder.class).build())
170+
.isInstanceOf(IllegalStateException.class)
171+
.hasMessageContaining("customized builder");
172+
});
173+
}
174+
175+
@Test
176+
void customizerShouldReturnInstanceNotANull() {
177+
contextRunner.withUserConfiguration(RestTemplateBuilderCustomizerReturnsNullConfig.class)
178+
.run((context) -> {
179+
assertThatThrownBy(() -> context.getBean(RestTemplateBuilder.class).build())
180+
.isInstanceOf(BeanCreationException.class)
181+
.hasMessageContaining("Error creating bean with name 'restTemplateBuilder'")
182+
.hasRootCauseInstanceOf(IllegalArgumentException.class)
183+
.hasRootCauseMessage("RestTemplateBuilderCustomizer returned null builder");
184+
});
185+
}
186+
160187
@Configuration(proxyBeanMethods = false)
161188
static class RestTemplateConfig {
162189

@@ -232,4 +259,23 @@ static class CustomHttpMessageConverter extends StringHttpMessageConverter {
232259

233260
}
234261

262+
@Configuration(proxyBeanMethods = false)
263+
static class RestTemplateBuilderCustomizerConfig {
264+
@Bean
265+
RestTemplateBuilderCustomizer restTemplateBuilderCustomizer() {
266+
return oldBuilder -> {
267+
final RestTemplateBuilder builder = Mockito.spy(oldBuilder);
268+
doThrow(new IllegalStateException("customized builder")).when(builder).build();
269+
return builder;
270+
};
271+
}
272+
}
273+
274+
@Configuration(proxyBeanMethods = false)
275+
static class RestTemplateBuilderCustomizerReturnsNullConfig {
276+
@Bean
277+
RestTemplateBuilderCustomizer restTemplateBuilderCustomizer() {
278+
return oldBuilder -> null;
279+
}
280+
}
235281
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.web.client;
18+
19+
/**
20+
* Callback interface that can be used to customize a {@link RestTemplateBuilder}.
21+
*
22+
* @author Ivo Smid
23+
* @see RestTemplateBuilder
24+
* @since 5.3.0
25+
*/
26+
@FunctionalInterface
27+
public interface RestTemplateBuilderCustomizer {
28+
/**
29+
* Callback to customize a {@link RestTemplateBuilder} instance.
30+
*
31+
* @param restTemplateBuilder the original builder to customize
32+
* @return customized builder instance
33+
*/
34+
RestTemplateBuilder customize(RestTemplateBuilder restTemplateBuilder);
35+
}

0 commit comments

Comments
 (0)