Skip to content

Commit 538ede0

Browse files
author
Ryan Baxter
committed
Merge remote-tracking branch 'Upstream/master' into error-handle-invalid-hostnames-159
# Conflicts: # spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerInterceptor.java
2 parents 43f7810 + e1460f9 commit 538ede0

19 files changed

+537
-128
lines changed

docs/src/main/asciidoc/spring-cloud-commons.adoc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ application that includes that jar on its classpath.
217217

218218
=== Environment Changes
219219

220-
The application will listen for an `EnvironmentChangedEvent` and react
220+
The application will listen for an `EnvironmentChangeEvent` and react
221221
to the change in a couple of standard ways (additional
222222
`ApplicationListeners` can be added as `@Beans` by the user in the
223-
normal way). When an `EnvironmentChangedEvent` is observed it will
223+
normal way). When an `EnvironmentChangeEvent` is observed it will
224224
have a list of key values that have changed, and the application will
225225
use those to:
226226

@@ -231,12 +231,12 @@ Note that the Config Client does not by default poll for changes in
231231
the `Environment`, and generally we would not recommend that approach
232232
for detecting changes (although you could set it up with a
233233
`@Scheduled` annotation). If you have a scaled-out client application
234-
then it is better to broadcast the `EnvironmentChangedEvent` to all
234+
then it is better to broadcast the `EnvironmentChangeEvent` to all
235235
the instances instead of having them polling for changes (e.g. using
236236
the https://github.com/spring-cloud/spring-cloud-bus[Spring Cloud
237237
Bus]).
238238

239-
The `EnvironmentChangedEvent` covers a large class of refresh use
239+
The `EnvironmentChangeEvent` covers a large class of refresh use
240240
cases, as long as you can actually make a change to the `Environment`
241241
and publish the event (those APIs are public and part of core
242242
Spring). You can verify the changes are bound to
@@ -363,7 +363,7 @@ for details of how the `RestTemplate` is set up.
363363

364364
A load balanced `RestTemplate` can be configured to retry failed requests.
365365
By default this logic is disabled, you can enable it by setting
366-
`spring.cloud.loadbalancer.retry=true`. The load balanced `RestTemplate` will
366+
`spring.cloud.loadbalancer.retry.enabled=true`. The load balanced `RestTemplate` will
367367
honor some of the Ribbon configuration values related to retrying failed requests.
368368
The properties you can use are `client.ribbon.MaxAutoRetries`,
369369
`client.ribbon.MaxAutoRetriesNextServer`, and `client.ribbon.OkToRetryOnAllOperations`.

spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,25 @@ public interface DiscoveryClient {
3131
* A human readable description of the implementation, used in HealthIndicator
3232
* @return the description
3333
*/
34-
public String description();
34+
String description();
3535

3636
/**
37+
* @deprecated use the {@link org.springframework.cloud.client.serviceregistry.Registration} bean instead
38+
*
3739
* @return ServiceInstance with information used to register the local service
3840
*/
39-
public ServiceInstance getLocalServiceInstance();
41+
ServiceInstance getLocalServiceInstance();
4042

4143
/**
4244
* Get all ServiceInstances associated with a particular serviceId
4345
* @param serviceId the serviceId to query
4446
* @return a List of ServiceInstance
4547
*/
46-
public List<ServiceInstance> getInstances(String serviceId);
48+
List<ServiceInstance> getInstances(String serviceId);
4749

4850
/**
4951
* @return all known service ids
5052
*/
51-
public List<String> getServices();
53+
List<String> getServices();
5254

5355
}

spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryLifecycle.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
/**
2323
* @author Spencer Gibb
24+
* @deprecated use {@link org.springframework.cloud.client.serviceregistry.AutoServiceRegistration} instead. This class will be removed in the next release train.
2425
*/
26+
@Deprecated
2527
public interface DiscoveryLifecycle extends SmartLifecycle, Ordered {
2628
}

spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2015 the original author or authors.
2+
* Copyright 2013-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2727
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
29-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3029
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3130
import org.springframework.context.annotation.Bean;
3231
import org.springframework.context.annotation.Configuration;
@@ -39,6 +38,7 @@
3938
*
4039
* @author Spencer Gibb
4140
* @author Dave Syer
41+
* @author Will Tran
4242
*/
4343
@Configuration
4444
@ConditionalOnClass(RestTemplate.class)
@@ -65,12 +65,24 @@ public void afterSingletonsInstantiated() {
6565
};
6666
}
6767

68+
@Autowired(required = false)
69+
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
70+
71+
@Bean
72+
@ConditionalOnMissingBean
73+
public LoadBalancerRequestFactory loadBalancerRequestFactory(
74+
LoadBalancerClient loadBalancerClient) {
75+
return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
76+
}
77+
6878
@Configuration
6979
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
7080
static class LoadBalancerInterceptorConfig {
7181
@Bean
72-
public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient) {
73-
return new LoadBalancerInterceptor(loadBalancerClient);
82+
public LoadBalancerInterceptor ribbonInterceptor(
83+
LoadBalancerClient loadBalancerClient,
84+
LoadBalancerRequestFactory requestFactory) {
85+
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
7486
}
7587

7688
@Bean
@@ -108,8 +120,10 @@ public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {
108120
@Bean
109121
public RetryLoadBalancerInterceptor ribbonInterceptor(
110122
LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
111-
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory) {
112-
return new RetryLoadBalancerInterceptor(loadBalancerClient, retryTemplate(), properties, lbRetryPolicyFactory);
123+
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
124+
LoadBalancerRequestFactory requestFactory) {
125+
return new RetryLoadBalancerInterceptor(loadBalancerClient, retryTemplate(), properties,
126+
lbRetryPolicyFactory, requestFactory);
113127
}
114128

115129
@Bean

spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerInterceptor.java

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2015 the original author or authors.
2+
* Copyright 2013-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
1818

1919
import java.io.IOException;
2020
import java.net.URI;
21-
import org.springframework.cloud.client.ServiceInstance;
21+
2222
import org.springframework.http.HttpRequest;
2323
import org.springframework.http.client.ClientHttpRequestExecution;
2424
import org.springframework.http.client.ClientHttpRequestInterceptor;
@@ -29,13 +29,21 @@
2929
* @author Spencer Gibb
3030
* @author Dave Syer
3131
* @author Ryan Baxter
32+
* @author William Tran
3233
*/
3334
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
3435

3536
private LoadBalancerClient loadBalancer;
37+
private LoadBalancerRequestFactory requestFactory;
3638

37-
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
39+
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
3840
this.loadBalancer = loadBalancer;
41+
this.requestFactory = requestFactory;
42+
}
43+
44+
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
45+
// for backwards compatibility
46+
this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
3947
}
4048

4149
@Override
@@ -44,16 +52,6 @@ public ClientHttpResponse intercept(final HttpRequest request, final byte[] body
4452
final URI originalUri = request.getURI();
4553
String serviceName = originalUri.getHost();
4654
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
47-
return this.loadBalancer.execute(serviceName,
48-
new LoadBalancerRequest<ClientHttpResponse>() {
49-
@Override
50-
public ClientHttpResponse apply(final ServiceInstance instance)
51-
throws Exception {
52-
HttpRequest serviceRequest = new ServiceRequestWrapper(request,
53-
instance, loadBalancer);
54-
return execution.execute(serviceRequest, body);
55-
}
56-
57-
});
55+
return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
5856
}
5957
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2017 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+
* http://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.cloud.client.loadbalancer;
18+
19+
import java.util.List;
20+
21+
import org.springframework.cloud.client.ServiceInstance;
22+
import org.springframework.http.HttpRequest;
23+
import org.springframework.http.client.ClientHttpRequestExecution;
24+
import org.springframework.http.client.ClientHttpResponse;
25+
26+
/**
27+
* Creates {@link LoadBalancerRequest}s for {@link LoadBalancerInterceptor} and
28+
* {@link RetryLoadBalancerInterceptor}. Applies
29+
* {@link LoadBalancerRequestTransformer}s to the intercepted
30+
* {@link HttpRequest}.
31+
*
32+
* @author William Tran
33+
*
34+
*/
35+
public class LoadBalancerRequestFactory {
36+
37+
private LoadBalancerClient loadBalancer;
38+
private List<LoadBalancerRequestTransformer> transformers;
39+
40+
public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer,
41+
List<LoadBalancerRequestTransformer> transformers) {
42+
this.loadBalancer = loadBalancer;
43+
this.transformers = transformers;
44+
}
45+
46+
public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer) {
47+
this.loadBalancer = loadBalancer;
48+
}
49+
50+
public LoadBalancerRequest<ClientHttpResponse> createRequest(final HttpRequest request,
51+
final byte[] body, final ClientHttpRequestExecution execution) {
52+
return new LoadBalancerRequest<ClientHttpResponse>() {
53+
54+
@Override
55+
public ClientHttpResponse apply(final ServiceInstance instance)
56+
throws Exception {
57+
HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, loadBalancer);
58+
if (transformers != null) {
59+
for (LoadBalancerRequestTransformer transformer : transformers) {
60+
serviceRequest = transformer.transformRequest(serviceRequest, instance);
61+
}
62+
}
63+
return execution.execute(serviceRequest, body);
64+
}
65+
66+
};
67+
}
68+
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2017 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+
* http://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+
package org.springframework.cloud.client.loadbalancer;
17+
18+
import org.springframework.cloud.client.ServiceInstance;
19+
import org.springframework.core.annotation.Order;
20+
import org.springframework.http.HttpRequest;
21+
22+
/**
23+
* Allows applications to transform the load balanced {@link HttpRequest} given
24+
* the chosen {@link ServiceInstance}
25+
*
26+
* @author Will Tran
27+
*/
28+
@Order(LoadBalancerRequestTransformer.DEFAULT_ORDER)
29+
public interface LoadBalancerRequestTransformer {
30+
public static final int DEFAULT_ORDER = 0;
31+
32+
HttpRequest transformRequest(HttpRequest request, ServiceInstance instance);
33+
}

spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/RetryLoadBalancerInterceptor.java

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2016-2017 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+
* http://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+
117
package org.springframework.cloud.client.loadbalancer;
218

319
import java.io.IOException;
@@ -16,22 +32,34 @@
1632

1733
/**
1834
* @author Ryan Baxter
35+
* @author Will Tran
1936
*/
2037
public class RetryLoadBalancerInterceptor implements ClientHttpRequestInterceptor {
2138

2239
private LoadBalancedRetryPolicyFactory lbRetryPolicyFactory;
2340
private RetryTemplate retryTemplate;
2441
private LoadBalancerClient loadBalancer;
2542
private LoadBalancerRetryProperties lbProperties;
43+
private LoadBalancerRequestFactory requestFactory;
2644

2745

2846
public RetryLoadBalancerInterceptor(LoadBalancerClient loadBalancer, RetryTemplate retryTemplate,
2947
LoadBalancerRetryProperties lbProperties,
30-
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory) {
48+
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
49+
LoadBalancerRequestFactory requestFactory) {
3150
this.loadBalancer = loadBalancer;
3251
this.lbRetryPolicyFactory = lbRetryPolicyFactory;
3352
this.retryTemplate = retryTemplate;
3453
this.lbProperties = lbProperties;
54+
this.requestFactory = requestFactory;
55+
}
56+
57+
public RetryLoadBalancerInterceptor(LoadBalancerClient loadBalancer, RetryTemplate retryTemplate,
58+
LoadBalancerRetryProperties lbProperties,
59+
LoadBalancedRetryPolicyFactory lbRetryPolicyFactory) {
60+
// for backwards compatibility
61+
this(loadBalancer, retryTemplate, lbProperties, lbRetryPolicyFactory,
62+
new LoadBalancerRequestFactory(loadBalancer));
3563
}
3664

3765
@Override
@@ -61,18 +89,7 @@ public ClientHttpResponse doWithRetry(RetryContext context)
6189
}
6290
return RetryLoadBalancerInterceptor.this.loadBalancer.execute(
6391
serviceName, serviceInstance,
64-
new LoadBalancerRequest<ClientHttpResponse>() {
65-
66-
@Override
67-
public ClientHttpResponse apply(
68-
final ServiceInstance instance)
69-
throws Exception {
70-
HttpRequest serviceRequest = new ServiceRequestWrapper(
71-
request, instance, loadBalancer);
72-
return execution.execute(serviceRequest, body);
73-
}
74-
75-
});
92+
requestFactory.createRequest(request, body, execution));
7693
}
7794
});
7895
}

0 commit comments

Comments
 (0)