diff --git a/spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java b/spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java
index 6904445fab6..3a3d02cc9c1 100644
--- a/spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java
+++ b/spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,11 +34,12 @@ import org.springframework.util.Assert;
* such as the {@link ClientHttpRequestFactory} to operate on.
*
*
Not intended to be used directly.
- * See {@link org.springframework.web.client.RestTemplate}.
+ * See {@link org.springframework.web.client.RestTemplate} for an entry point.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
+ * @see ClientHttpRequestFactory
* @see org.springframework.web.client.RestTemplate
*/
public abstract class HttpAccessor {
@@ -56,6 +57,7 @@ public abstract class HttpAccessor {
*
Note that the standard JDK HTTP library does not support the HTTP PATCH method.
* Configure the Apache HttpComponents or OkHttp request factory to enable PATCH.
* @see #createRequest(URI, HttpMethod)
+ * @see SimpleClientHttpRequestFactory
* @see org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory
* @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory
*/
diff --git a/spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java b/spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java
index ecb28598a3b..0147996b03a 100644
--- a/spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java
+++ b/spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,43 +23,83 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.InterceptingClientHttpRequestFactory;
+import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
/**
- * Base class for {@link org.springframework.web.client.RestTemplate} and other HTTP accessing gateway helpers, adding
- * interceptor-related properties to {@link HttpAccessor}'s common properties.
+ * Base class for {@link org.springframework.web.client.RestTemplate}
+ * and other HTTP accessing gateway helpers, adding interceptor-related
+ * properties to {@link HttpAccessor}'s common properties.
*
- *
Not intended to be used directly. See {@link org.springframework.web.client.RestTemplate}.
+ *
Not intended to be used directly.
+ * See {@link org.springframework.web.client.RestTemplate} for an entry point.
*
* @author Arjen Poutsma
+ * @author Juergen Hoeller
+ * @since 3.0
+ * @see ClientHttpRequestInterceptor
+ * @see InterceptingClientHttpRequestFactory
+ * @see org.springframework.web.client.RestTemplate
*/
public abstract class InterceptingHttpAccessor extends HttpAccessor {
- private List interceptors = new ArrayList<>();
+ private final List interceptors = new ArrayList<>();
+
+ @Nullable
+ private volatile ClientHttpRequestFactory interceptingRequestFactory;
+
/**
- * Sets the request interceptors that this accessor should use.
+ * Set the request interceptors that this accessor should use.
+ * The interceptors will get sorted according to their order
+ * once the {@link ClientHttpRequestFactory} will be built.
+ * @see #getRequestFactory()
+ * @see AnnotationAwareOrderComparator
*/
public void setInterceptors(List interceptors) {
- AnnotationAwareOrderComparator.sort(interceptors);
- this.interceptors = interceptors;
+ // Take getInterceptors() List as-is when passed in here
+ if (this.interceptors != interceptors) {
+ this.interceptors.clear();
+ this.interceptors.addAll(interceptors);
+ AnnotationAwareOrderComparator.sort(this.interceptors);
+ }
}
/**
- * Return the request interceptor that this accessor uses.
+ * Return the request interceptors that this accessor uses.
+ * The returned {@link List} is active and may get appended to.
*/
public List getInterceptors() {
- return interceptors;
+ return this.interceptors;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
+ super.setRequestFactory(requestFactory);
+ this.interceptingRequestFactory = null;
+ }
+
+ /**
+ * Overridden to expose an {@link InterceptingClientHttpRequestFactory}
+ * if necessary.
+ * @see #getInterceptors()
+ */
@Override
public ClientHttpRequestFactory getRequestFactory() {
- ClientHttpRequestFactory delegate = super.getRequestFactory();
- if (!CollectionUtils.isEmpty(getInterceptors())) {
- return new InterceptingClientHttpRequestFactory(delegate, getInterceptors());
+ List interceptors = getInterceptors();
+ if (!CollectionUtils.isEmpty(interceptors)) {
+ ClientHttpRequestFactory factory = this.interceptingRequestFactory;
+ if (factory == null) {
+ factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
+ this.interceptingRequestFactory = factory;
+ }
+ return factory;
}
else {
- return delegate;
+ return super.getRequestFactory();
}
}
diff --git a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java
index 3aec0538e1f..4acd8ae02eb 100644
--- a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java
+++ b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java
@@ -237,7 +237,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
/**
- * Return the message body converters.
+ * Return the list of message body converters.
+ * The returned {@link List} is active and may get appended to.
*/
public List> getMessageConverters() {
return this.messageConverters;
diff --git a/spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java b/spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java
index 0e515883a31..2bd99f98280 100644
--- a/spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java
+++ b/spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
package org.springframework.http.client.support;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@@ -32,6 +29,8 @@ import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
+import static org.junit.Assert.*;
+
/**
* Tests for {@link InterceptingHttpAccessor}.
*
@@ -40,7 +39,7 @@ import org.springframework.http.client.ClientHttpResponse;
public class InterceptingHttpAccessorTests {
@Test
- public void getInterceptors() throws Exception {
+ public void getInterceptors() {
TestInterceptingHttpAccessor accessor = new TestInterceptingHttpAccessor();
List interceptors = Arrays.asList(
new SecondClientHttpRequestInterceptor(),
@@ -55,22 +54,25 @@ public class InterceptingHttpAccessorTests {
assertThat(accessor.getInterceptors().get(2), Matchers.instanceOf(ThirdClientHttpRequestInterceptor.class));
}
+
private class TestInterceptingHttpAccessor extends InterceptingHttpAccessor {
}
+
@Order(1)
private class FirstClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+
@Override
- public ClientHttpResponse intercept(HttpRequest request, byte[] body,
- ClientHttpRequestExecution execution) throws IOException {
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
return null;
}
}
+
private class SecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor, Ordered {
+
@Override
- public ClientHttpResponse intercept(HttpRequest request, byte[] body,
- ClientHttpRequestExecution execution) throws IOException {
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
return null;
}
@@ -80,12 +82,13 @@ public class InterceptingHttpAccessorTests {
}
}
+
private class ThirdClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+
@Override
- public ClientHttpResponse intercept(HttpRequest request, byte[] body,
- ClientHttpRequestExecution execution) throws IOException {
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
return null;
}
}
-}
\ No newline at end of file
+}