From 269bb9148c9b21d76f38dfe7944da37b5accb7c8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 22 Aug 2016 20:37:28 +0100 Subject: [PATCH] Add methods to RestTemplateBuilder for configuring interceptors Closes gh-6701 --- .../boot/web/client/RestTemplateBuilder.java | 110 +++++++++++++++--- .../web/client/RestTemplateBuilderTests.java | 59 ++++++++++ 2 files changed, 153 insertions(+), 16 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java b/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java index 0b757dbc4c..e36fef8540 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java @@ -30,6 +30,7 @@ import java.util.Set; import org.springframework.beans.BeanUtils; import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper; import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.support.BasicAuthorizationInterceptor; import org.springframework.http.converter.HttpMessageConverter; @@ -93,6 +94,8 @@ public class RestTemplateBuilder { private final Set requestFactoryCustomizers; + private final Set interceptors; + /** * Create a new {@link RestTemplateBuilder} instance. * @param customizers any {@link RestTemplateCustomizer RestTemplateCustomizers} that @@ -110,6 +113,7 @@ public class RestTemplateBuilder { this.restTemplateCustomizers = Collections.unmodifiableSet( new LinkedHashSet(Arrays.asList(customizers))); this.requestFactoryCustomizers = Collections.emptySet(); + this.interceptors = Collections.emptySet(); } private RestTemplateBuilder(boolean detectRequestFactory, String rootUri, @@ -118,7 +122,8 @@ public class RestTemplateBuilder { UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler, BasicAuthorizationInterceptor basicAuthorization, Set restTemplateCustomizers, - Set requestFactoryCustomizers) { + Set requestFactoryCustomizers, + Set interceptors) { super(); this.detectRequestFactory = detectRequestFactory; this.rootUri = rootUri; @@ -129,6 +134,7 @@ public class RestTemplateBuilder { this.basicAuthorization = basicAuthorization; this.restTemplateCustomizers = restTemplateCustomizers; this.requestFactoryCustomizers = requestFactoryCustomizers; + this.interceptors = interceptors; } /** @@ -142,7 +148,7 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(detectRequestFactory, this.rootUri, this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -155,12 +161,13 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, rootUri, this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** * Set the {@link HttpMessageConverter HttpMessageConverters} that should be used with - * the {@link RestTemplate}. Setting this value will replace any previously calls. + * the {@link RestTemplate}. Setting this value will replace any previously configured + * converters. * @param messageConverters the converters to set * @return a new builder instance * @see #additionalMessageConverters(HttpMessageConverter...) @@ -173,7 +180,8 @@ public class RestTemplateBuilder { /** * Set the {@link HttpMessageConverter HttpMessageConverters} that should be used with - * the {@link RestTemplate}. Setting this value will replace any previously calls. + * the {@link RestTemplate}. Setting this value will replace any previously configured + * converters. * @param messageConverters the converters to set * @return a new builder instance * @see #additionalMessageConverters(HttpMessageConverter...) @@ -186,7 +194,7 @@ public class RestTemplateBuilder { new LinkedHashSet>(messageConverters)), this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -215,7 +223,8 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, append(this.messageConverters, messageConverters), this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, - this.restTemplateCustomizers, this.requestFactoryCustomizers); + this.restTemplateCustomizers, this.requestFactoryCustomizers, + this.interceptors); } /** @@ -231,7 +240,72 @@ public class RestTemplateBuilder { new RestTemplate().getMessageConverters())), this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); + } + + /** + * Set the {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} that + * should be used with the {@link RestTemplate}. Setting this value will replace any + * previously defined interceptors. + * @param interceptors the interceptors to set + * @return a new builder instance + * @see #additionalInterceptors(ClientHttpRequestInterceptor...) + * @since 1.4.1 + */ + public RestTemplateBuilder interceptors( + ClientHttpRequestInterceptor... interceptors) { + Assert.notNull(interceptors, "interceptors must not be null"); + return interceptors(Arrays.asList(interceptors)); + } + + /** + * Set the {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} that + * should be used with the {@link RestTemplate}. Setting this value will replace any + * previously defined interceptors. + * @param interceptors the interceptors to set + * @return a new builder instance + * @see #additionalInterceptors(ClientHttpRequestInterceptor...) + * @since 1.4.1 + */ + public RestTemplateBuilder interceptors( + Collection interceptors) { + Assert.notNull(interceptors, "interceptors must not be null"); + return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, + this.messageConverters, this.requestFactory, this.uriTemplateHandler, + this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, + this.requestFactoryCustomizers, Collections.unmodifiableSet( + new LinkedHashSet(interceptors))); + } + + /** + * Add additional {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} + * that should be used with the {@link RestTemplate}. + * @param interceptors the interceptors to add + * @return a new builder instance + * @see #interceptors(ClientHttpRequestInterceptor...) + * @since 1.4.1 + */ + public RestTemplateBuilder additionalInterceptors( + ClientHttpRequestInterceptor... interceptors) { + Assert.notNull(interceptors, "interceptors must not be null"); + return additionalInterceptors(Arrays.asList(interceptors)); + } + + /** + * Add additional {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} + * that should be used with the {@link RestTemplate}. + * @param interceptors the interceptors to add + * @return a new builder instance + * @see #interceptors(ClientHttpRequestInterceptor...) + * @since 1.4.1 + */ + public RestTemplateBuilder additionalInterceptors( + Collection interceptors) { + Assert.notNull(interceptors, "interceptors must not be null"); + return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, + this.messageConverters, this.requestFactory, this.uriTemplateHandler, + this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, + this.requestFactoryCustomizers, append(this.interceptors, interceptors)); } /** @@ -257,7 +331,7 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, this.messageConverters, requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -271,7 +345,7 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, this.messageConverters, this.requestFactory, uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -285,7 +359,7 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, this.messageConverters, this.requestFactory, this.uriTemplateHandler, errorHandler, this.basicAuthorization, this.restTemplateCustomizers, - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -299,7 +373,8 @@ public class RestTemplateBuilder { return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri, this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, new BasicAuthorizationInterceptor(username, password), - this.restTemplateCustomizers, this.requestFactoryCustomizers); + this.restTemplateCustomizers, this.requestFactoryCustomizers, + this.interceptors); } /** @@ -336,7 +411,7 @@ public class RestTemplateBuilder { this.errorHandler, this.basicAuthorization, Collections.unmodifiableSet(new LinkedHashSet( restTemplateCustomizers)), - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -369,7 +444,7 @@ public class RestTemplateBuilder { this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, append(this.restTemplateCustomizers, customizers), - this.requestFactoryCustomizers); + this.requestFactoryCustomizers, this.interceptors); } /** @@ -384,7 +459,8 @@ public class RestTemplateBuilder { this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, append(this.requestFactoryCustomizers, - new ConnectTimeoutRequestFactoryCustomizer(connectTimeout))); + new ConnectTimeoutRequestFactoryCustomizer(connectTimeout)), + this.interceptors); } /** @@ -399,7 +475,8 @@ public class RestTemplateBuilder { this.messageConverters, this.requestFactory, this.uriTemplateHandler, this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers, append(this.requestFactoryCustomizers, - new ReadTimeoutRequestFactoryCustomizer(readTimeout))); + new ReadTimeoutRequestFactoryCustomizer(readTimeout)), + this.interceptors); } /** @@ -457,6 +534,7 @@ public class RestTemplateBuilder { customizer.customize(restTemplate); } } + restTemplate.getInterceptors().addAll(this.interceptors); return restTemplate; } diff --git a/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java b/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java index c7e7d51736..6cabe7810a 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/client/RestTemplateBuilderTests.java @@ -72,6 +72,9 @@ public class RestTemplateBuilderTests { @Mock private HttpMessageConverter messageConverter; + @Mock + private ClientHttpRequestInterceptor interceptor; + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -203,6 +206,62 @@ public class RestTemplateBuilderTests { .hasSameSizeAs(new RestTemplate().getMessageConverters()); } + @Test + public void interceptorsWhenInterceptorsAreNullShouldThrowException() + throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("interceptors must not be null"); + this.builder.interceptors((ClientHttpRequestInterceptor[]) null); + } + + @Test + public void interceptorsCollectionWhenInterceptorsAreNullShouldThrowException() + throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("interceptors must not be null"); + this.builder.interceptors((Set) null); + } + + @Test + public void interceptorsShouldApply() throws Exception { + RestTemplate template = this.builder.interceptors(this.interceptor).build(); + assertThat(template.getInterceptors()).containsOnly(this.interceptor); + } + + @Test + public void interceptorsShouldReplaceExisting() throws Exception { + RestTemplate template = this.builder + .interceptors(mock(ClientHttpRequestInterceptor.class)) + .interceptors(Collections.singleton(this.interceptor)).build(); + assertThat(template.getInterceptors()).containsOnly(this.interceptor); + } + + @Test + public void additionalInterceptorsWhenInterceptorsAreNullShouldThrowException() + throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("interceptors must not be null"); + this.builder.additionalInterceptors((ClientHttpRequestInterceptor[]) null); + } + + @Test + public void additionalInterceptorsCollectionWhenInterceptorsAreNullShouldThrowException() + throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("interceptors must not be null"); + this.builder.additionalInterceptors((Set) null); + } + + @Test + public void additionalInterceptorsShouldAddToExisting() throws Exception { + ClientHttpRequestInterceptor interceptor = mock( + ClientHttpRequestInterceptor.class); + RestTemplate template = this.builder.interceptors(interceptor) + .additionalInterceptors(this.interceptor).build(); + assertThat(template.getInterceptors()).containsOnly(interceptor, + this.interceptor); + } + @Test public void requestFactoryClassWhenFactoryIsNullShouldThrowException() throws Exception {