Polish "Add duration support for setConnectTimout and setReadTimeout"
See gh-13355
This commit is contained in:
parent
83f7df920b
commit
8691d01aaf
|
@ -19,12 +19,14 @@ package org.springframework.boot.web.client;
|
|||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
@ -76,7 +78,7 @@ public class RestTemplateBuilder {
|
|||
|
||||
private final Set<RestTemplateCustomizer> restTemplateCustomizers;
|
||||
|
||||
private final Set<RequestFactoryCustomizer> requestFactoryCustomizers;
|
||||
private final RequestFactoryCustomizer requestFactoryCustomizer;
|
||||
|
||||
private final Set<ClientHttpRequestInterceptor> interceptors;
|
||||
|
||||
|
@ -96,7 +98,7 @@ public class RestTemplateBuilder {
|
|||
this.basicAuthorization = null;
|
||||
this.restTemplateCustomizers = Collections
|
||||
.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(customizers)));
|
||||
this.requestFactoryCustomizers = Collections.emptySet();
|
||||
this.requestFactoryCustomizer = new RequestFactoryCustomizer();
|
||||
this.interceptors = Collections.emptySet();
|
||||
}
|
||||
|
||||
|
@ -106,7 +108,7 @@ public class RestTemplateBuilder {
|
|||
UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler,
|
||||
BasicAuthorizationInterceptor basicAuthorization,
|
||||
Set<RestTemplateCustomizer> restTemplateCustomizers,
|
||||
Set<RequestFactoryCustomizer> requestFactoryCustomizers,
|
||||
RequestFactoryCustomizer requestFactoryCustomizer,
|
||||
Set<ClientHttpRequestInterceptor> interceptors) {
|
||||
this.detectRequestFactory = detectRequestFactory;
|
||||
this.rootUri = rootUri;
|
||||
|
@ -116,7 +118,7 @@ public class RestTemplateBuilder {
|
|||
this.errorHandler = errorHandler;
|
||||
this.basicAuthorization = basicAuthorization;
|
||||
this.restTemplateCustomizers = restTemplateCustomizers;
|
||||
this.requestFactoryCustomizers = requestFactoryCustomizers;
|
||||
this.requestFactoryCustomizer = requestFactoryCustomizer;
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
|
||||
|
@ -131,7 +133,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
|
@ -145,7 +147,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
|
@ -179,7 +181,7 @@ public class RestTemplateBuilder {
|
|||
new LinkedHashSet<HttpMessageConverter<?>>(messageConverters)),
|
||||
this.requestFactorySupplier, this.uriTemplateHandler, this.errorHandler,
|
||||
this.basicAuthorization, this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,7 +211,7 @@ public class RestTemplateBuilder {
|
|||
append(this.messageConverters, messageConverters),
|
||||
this.requestFactorySupplier, this.uriTemplateHandler, this.errorHandler,
|
||||
this.basicAuthorization, this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,7 +227,7 @@ public class RestTemplateBuilder {
|
|||
new LinkedHashSet<>(new RestTemplate().getMessageConverters())),
|
||||
this.requestFactorySupplier, this.uriTemplateHandler, this.errorHandler,
|
||||
this.basicAuthorization, this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,7 +260,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
Collections.unmodifiableSet(new LinkedHashSet<>(interceptors)));
|
||||
}
|
||||
|
||||
|
@ -290,7 +292,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
append(this.interceptors, interceptors));
|
||||
}
|
||||
|
||||
|
@ -332,7 +334,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, requestFactorySupplier, this.uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -346,7 +348,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier, uriTemplateHandler,
|
||||
this.errorHandler, this.basicAuthorization, this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -360,7 +362,7 @@ public class RestTemplateBuilder {
|
|||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
|
@ -376,7 +378,7 @@ public class RestTemplateBuilder {
|
|||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler,
|
||||
new BasicAuthorizationInterceptor(username, password),
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizers,
|
||||
this.restTemplateCustomizers, this.requestFactoryCustomizer,
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
|
@ -414,7 +416,7 @@ public class RestTemplateBuilder {
|
|||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
Collections.unmodifiableSet(new LinkedHashSet<RestTemplateCustomizer>(
|
||||
restTemplateCustomizers)),
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -447,7 +449,22 @@ public class RestTemplateBuilder {
|
|||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
append(this.restTemplateCustomizers, customizers),
|
||||
this.requestFactoryCustomizers, this.interceptors);
|
||||
this.requestFactoryCustomizer, this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout on the underlying {@link ClientHttpRequestFactory}.
|
||||
* @param connectTimeout the connection timeout
|
||||
* @return a new builder instance.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public RestTemplateBuilder setConnectTimeout(Duration connectTimeout) {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers,
|
||||
this.requestFactoryCustomizer.connectTimeout(connectTimeout),
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -455,14 +472,25 @@ public class RestTemplateBuilder {
|
|||
* {@link ClientHttpRequestFactory}.
|
||||
* @param connectTimeout the connection timeout in milliseconds
|
||||
* @return a new builder instance.
|
||||
* @deprecated since 2.1.0 in favor of {@link #setConnectTimeout(Duration)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RestTemplateBuilder setConnectTimeout(int connectTimeout) {
|
||||
return setConnectTimeout(Duration.ofMillis(connectTimeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the read timeout on the underlying {@link ClientHttpRequestFactory}.
|
||||
* @param readTimeout the read timeout
|
||||
* @return a new builder instance.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public RestTemplateBuilder setReadTimeout(Duration readTimeout) {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers,
|
||||
append(this.requestFactoryCustomizers,
|
||||
new ConnectTimeoutRequestFactoryCustomizer(connectTimeout)),
|
||||
this.requestFactoryCustomizer.readTimeout(readTimeout),
|
||||
this.interceptors);
|
||||
}
|
||||
|
||||
|
@ -471,15 +499,11 @@ public class RestTemplateBuilder {
|
|||
* {@link ClientHttpRequestFactory}.
|
||||
* @param readTimeout the read timeout in milliseconds
|
||||
* @return a new builder instance.
|
||||
* @deprecated since 2.1.0 in favour of {@link #setReadTimeout(Duration)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RestTemplateBuilder setReadTimeout(int readTimeout) {
|
||||
return new RestTemplateBuilder(this.detectRequestFactory, this.rootUri,
|
||||
this.messageConverters, this.requestFactorySupplier,
|
||||
this.uriTemplateHandler, this.errorHandler, this.basicAuthorization,
|
||||
this.restTemplateCustomizers,
|
||||
append(this.requestFactoryCustomizers,
|
||||
new ReadTimeoutRequestFactoryCustomizer(readTimeout)),
|
||||
this.interceptors);
|
||||
return setReadTimeout(Duration.ofMillis(readTimeout));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -549,105 +573,103 @@ public class RestTemplateBuilder {
|
|||
requestFactory = new ClientHttpRequestFactorySupplier().get();
|
||||
}
|
||||
if (requestFactory != null) {
|
||||
ClientHttpRequestFactory unwrappedRequestFactory = unwrapRequestFactoryIfNecessary(
|
||||
requestFactory);
|
||||
for (RequestFactoryCustomizer customizer : this.requestFactoryCustomizers) {
|
||||
customizer.customize(unwrappedRequestFactory);
|
||||
if (this.requestFactoryCustomizer != null) {
|
||||
this.requestFactoryCustomizer.accept(requestFactory);
|
||||
}
|
||||
restTemplate.setRequestFactory(requestFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private ClientHttpRequestFactory unwrapRequestFactoryIfNecessary(
|
||||
ClientHttpRequestFactory requestFactory) {
|
||||
if (!(requestFactory instanceof AbstractClientHttpRequestFactoryWrapper)) {
|
||||
return requestFactory;
|
||||
}
|
||||
ClientHttpRequestFactory unwrappedRequestFactory = requestFactory;
|
||||
Field field = ReflectionUtils.findField(
|
||||
AbstractClientHttpRequestFactoryWrapper.class, "requestFactory");
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
do {
|
||||
unwrappedRequestFactory = (ClientHttpRequestFactory) ReflectionUtils
|
||||
.getField(field, unwrappedRequestFactory);
|
||||
}
|
||||
while (unwrappedRequestFactory instanceof AbstractClientHttpRequestFactoryWrapper);
|
||||
return unwrappedRequestFactory;
|
||||
}
|
||||
|
||||
private <T> Set<T> append(Set<T> set, T addition) {
|
||||
Set<T> result = new LinkedHashSet<>(set != null ? set : Collections.emptySet());
|
||||
result.add(addition);
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
private <T> Set<T> append(Set<T> set, Collection<? extends T> additions) {
|
||||
Set<T> result = new LinkedHashSet<>(set != null ? set : Collections.emptySet());
|
||||
result.addAll(additions);
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strategy interface used to customize the {@link ClientHttpRequestFactory}.
|
||||
*/
|
||||
private interface RequestFactoryCustomizer {
|
||||
private static class RequestFactoryCustomizer
|
||||
implements Consumer<ClientHttpRequestFactory> {
|
||||
|
||||
void customize(ClientHttpRequestFactory factory);
|
||||
private final Duration connectTimeout;
|
||||
|
||||
}
|
||||
private final Duration readTimeout;
|
||||
|
||||
/**
|
||||
* {@link RequestFactoryCustomizer} to call a "set timeout" method.
|
||||
*/
|
||||
private abstract static class TimeoutRequestFactoryCustomizer
|
||||
implements RequestFactoryCustomizer {
|
||||
RequestFactoryCustomizer() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
private final int timeout;
|
||||
private RequestFactoryCustomizer(Duration connectTimeout, Duration readTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
|
||||
private final String methodName;
|
||||
public RequestFactoryCustomizer connectTimeout(Duration connectTimeout) {
|
||||
return new RequestFactoryCustomizer(connectTimeout, this.readTimeout);
|
||||
}
|
||||
|
||||
TimeoutRequestFactoryCustomizer(int timeout, String methodName) {
|
||||
this.timeout = timeout;
|
||||
this.methodName = methodName;
|
||||
public RequestFactoryCustomizer readTimeout(Duration readTimeout) {
|
||||
return new RequestFactoryCustomizer(this.connectTimeout, readTimeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ClientHttpRequestFactory factory) {
|
||||
ReflectionUtils.invokeMethod(findMethod(factory), factory, this.timeout);
|
||||
}
|
||||
|
||||
private Method findMethod(ClientHttpRequestFactory factory) {
|
||||
Method method = ReflectionUtils.findMethod(factory.getClass(),
|
||||
this.methodName, int.class);
|
||||
if (method != null) {
|
||||
return method;
|
||||
public void accept(ClientHttpRequestFactory requestFactory) {
|
||||
ClientHttpRequestFactory unwrappedRequestFactory = unwrapRequestFactoryIfNecessary(
|
||||
requestFactory);
|
||||
if (this.connectTimeout != null) {
|
||||
new TimeoutRequestFactoryCustomizer(this.connectTimeout,
|
||||
"setConnectTimeout").customize(unwrappedRequestFactory);
|
||||
}
|
||||
if (this.readTimeout != null) {
|
||||
new TimeoutRequestFactoryCustomizer(this.readTimeout, "setReadTimeout")
|
||||
.customize(unwrappedRequestFactory);
|
||||
}
|
||||
throw new IllegalStateException("Request factory " + factory.getClass()
|
||||
+ " does not have a " + this.methodName + "(int) method");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link RequestFactoryCustomizer} to set the read timeout.
|
||||
*/
|
||||
private static class ReadTimeoutRequestFactoryCustomizer
|
||||
extends TimeoutRequestFactoryCustomizer {
|
||||
|
||||
ReadTimeoutRequestFactoryCustomizer(int readTimeout) {
|
||||
super(readTimeout, "setReadTimeout");
|
||||
private ClientHttpRequestFactory unwrapRequestFactoryIfNecessary(
|
||||
ClientHttpRequestFactory requestFactory) {
|
||||
if (!(requestFactory instanceof AbstractClientHttpRequestFactoryWrapper)) {
|
||||
return requestFactory;
|
||||
}
|
||||
ClientHttpRequestFactory unwrappedRequestFactory = requestFactory;
|
||||
Field field = ReflectionUtils.findField(
|
||||
AbstractClientHttpRequestFactoryWrapper.class, "requestFactory");
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
do {
|
||||
unwrappedRequestFactory = (ClientHttpRequestFactory) ReflectionUtils
|
||||
.getField(field, unwrappedRequestFactory);
|
||||
}
|
||||
while (unwrappedRequestFactory instanceof AbstractClientHttpRequestFactoryWrapper);
|
||||
return unwrappedRequestFactory;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* {@link ClientHttpRequestFactory} customizer to call a "set timeout" method.
|
||||
*/
|
||||
private static final class TimeoutRequestFactoryCustomizer {
|
||||
|
||||
/**
|
||||
* {@link RequestFactoryCustomizer} to set the connection timeout.
|
||||
*/
|
||||
private static class ConnectTimeoutRequestFactoryCustomizer
|
||||
extends TimeoutRequestFactoryCustomizer {
|
||||
private final Duration timeout;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
TimeoutRequestFactoryCustomizer(Duration timeout, String methodName) {
|
||||
this.timeout = timeout;
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
void customize(ClientHttpRequestFactory factory) {
|
||||
ReflectionUtils.invokeMethod(findMethod(factory), factory,
|
||||
Math.toIntExact(this.timeout.toMillis()));
|
||||
}
|
||||
|
||||
private Method findMethod(ClientHttpRequestFactory factory) {
|
||||
Method method = ReflectionUtils.findMethod(factory.getClass(),
|
||||
this.methodName, int.class);
|
||||
if (method != null) {
|
||||
return method;
|
||||
}
|
||||
throw new IllegalStateException("Request factory " + factory.getClass()
|
||||
+ " does not have a " + this.methodName + "(int) method");
|
||||
}
|
||||
|
||||
ConnectTimeoutRequestFactoryCustomizer(int connectTimeout) {
|
||||
super(connectTimeout, "setConnectTimeout");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue