Skip to content

Commit 87ec1d7

Browse files
Set up RestClient-based TransportClientFactories (#4363)
1 parent 887d767 commit 87ec1d7

22 files changed

+726
-383
lines changed

docs/modules/ROOT/pages/spring-cloud-netflix.adoc

+6-1
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,18 @@ NOTE: Because of a limitation in Eureka, it is not possible to support per-serve
9898

9999
If you want to customize the RestTemplate used by the Eureka HTTP Client you may want to create a bean of `EurekaClientHttpRequestFactorySupplier` and provide your own logic for generating a `ClientHttpRequestFactory` instance.
100100

101-
All default timeout-related properties for RestTemplate used by the Eureka HTTP Client are set to 3 minutes (in keeping with Apache HC5 default `RequestConfig` and `SocketConfig`). Therefore, to specify the timeout values, you must specify the value directly with the properties in `eureka.client.rest-template-timeout`. (All timeout properties are in milliseconds.)
101+
All default timeout-related properties for RestTemplate and RestClient used by the Eureka HTTP Client are set to 3 minutes (in keeping with Apache HC5 default `RequestConfig` and `SocketConfig`). Therefore, to specify the timeout values, you must specify the value directly with the properties in `eureka.client.rest-template-timeout` or `eureka.client.restclient.timeout`. All timeout properties are in milliseconds.
102102

103103
.application.yml
104104
[source,yaml]
105105
----
106106
eureka:
107107
client:
108+
restclient:
109+
timeout:
110+
connect-timeout: 5000
111+
connect-request-timeout: 8000
112+
socket-timeout: 10000
108113
rest-template-timeout:
109114
connect-timeout: 5000
110115
connect-request-timeout: 8000

docs/modules/ROOT/partials/_configprops.adoc

+107-104
Large diffs are not rendered by default.

spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientTests.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
import org.springframework.boot.SpringBootConfiguration;
2424
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
25-
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
2625
import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier;
2726
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
2827
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories;
@@ -33,7 +32,7 @@
3332

3433
public class EurekaClientTests extends BaseCertTests {
3534

36-
private static final Log log = LogFactory.getLog(EurekaClientTests.class);
35+
private static final Log LOG = LogFactory.getLog(EurekaClientTests.class);
3736

3837
static EurekaServerRunner server;
3938

@@ -44,7 +43,7 @@ public static void setupAll() {
4443
server = startEurekaServer(EurekaClientTests.TestEurekaServer.class);
4544
service = startService(server, EurekaClientTests.TestApp.class);
4645
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
47-
log.info("Successfully asserted that Jersey will be used");
46+
LOG.info("Successfully asserted that Jersey will be used");
4847
waitForRegistration(() -> new EurekaClientTests().createEurekaClient());
4948
}
5049

@@ -59,9 +58,8 @@ public static class TestApp {
5958

6059
@Bean
6160
public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories(
62-
DiscoveryClientOptionalArgsConfiguration configuration,
6361
RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) {
64-
return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs);
62+
return new RestTemplateTransportClientFactories(discoveryClientOptionalArgs);
6563
}
6664

6765
@Bean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2018-2024 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.cloud.netflix.eureka;
18+
19+
import java.io.IOException;
20+
import java.security.GeneralSecurityException;
21+
22+
import org.apache.commons.logging.Log;
23+
import org.apache.commons.logging.LogFactory;
24+
import org.junit.jupiter.api.AfterAll;
25+
import org.junit.jupiter.api.BeforeAll;
26+
27+
import org.springframework.boot.SpringBootConfiguration;
28+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
29+
import org.springframework.cloud.configuration.TlsProperties;
30+
import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier;
31+
import org.springframework.cloud.netflix.eureka.http.RestClientDiscoveryClientOptionalArgs;
32+
import org.springframework.cloud.netflix.eureka.http.RestClientTransportClientFactories;
33+
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
34+
import org.springframework.context.annotation.Bean;
35+
import org.springframework.web.client.RestClient;
36+
37+
import static org.assertj.core.api.Assertions.assertThat;
38+
import static org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration.setupTLS;
39+
40+
/**
41+
* Tests for verifying TLS setup with {@link RestClientTransportClientFactories}.
42+
*
43+
* @author Olga Maciaszek-Sharma
44+
*/
45+
public class RestClientEurekaClientTests extends BaseCertTests {
46+
47+
private static final Log LOG = LogFactory.getLog(RestClientEurekaClientTests.class);
48+
49+
private static EurekaServerRunner server;
50+
51+
private static EurekaClientRunner service;
52+
53+
@BeforeAll
54+
public static void setupAll() {
55+
server = startEurekaServer(TestEurekaServer.class);
56+
service = startService(server, TestApp.class);
57+
// Will use RestClient
58+
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestClientDiscoveryClientOptionalArgs.class);
59+
LOG.info("Successfully asserted that RestClient will be used");
60+
waitForRegistration(() -> new RestClientEurekaClientTests().createEurekaClient());
61+
}
62+
63+
@AfterAll
64+
public static void tearDownAll() {
65+
stopService(service);
66+
stopEurekaServer(server);
67+
}
68+
69+
@Override
70+
EurekaClientRunner createEurekaClient() {
71+
return new EurekaClientRunner(TestApp.class, server);
72+
}
73+
74+
@SpringBootConfiguration
75+
@EnableAutoConfiguration
76+
public static class TestApp {
77+
78+
// Want to force reusing exactly the same bean as on production without excluding
79+
// jersey from the classpath
80+
@Bean
81+
public RestClientDiscoveryClientOptionalArgs forceRestClientDiscoveryClientOptionalArgs(
82+
TlsProperties tlsProperties,
83+
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier)
84+
throws GeneralSecurityException, IOException {
85+
RestClientDiscoveryClientOptionalArgs result = new RestClientDiscoveryClientOptionalArgs(
86+
eurekaClientHttpRequestFactorySupplier, RestClient::builder);
87+
setupTLS(result, tlsProperties);
88+
return result;
89+
}
90+
91+
@Bean
92+
public RestClientTransportClientFactories forceRestClientTransportClientFactories(
93+
RestClientDiscoveryClientOptionalArgs discoveryClientOptionalArgs) {
94+
return new RestClientTransportClientFactories(discoveryClientOptionalArgs);
95+
}
96+
97+
}
98+
99+
@SpringBootConfiguration
100+
@EnableAutoConfiguration
101+
@EnableEurekaServer
102+
public static class TestEurekaServer {
103+
104+
}
105+
106+
}

spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestTemplateEurekaClientTests.java

+16-40
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,19 @@
2424
import org.junit.jupiter.api.AfterAll;
2525
import org.junit.jupiter.api.BeforeAll;
2626

27-
import org.springframework.beans.BeansException;
28-
import org.springframework.beans.factory.ObjectProvider;
2927
import org.springframework.boot.SpringBootConfiguration;
3028
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3129
import org.springframework.boot.web.client.RestTemplateBuilder;
3230
import org.springframework.cloud.configuration.TlsProperties;
33-
import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
31+
import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier;
3432
import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier;
3533
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
3634
import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories;
3735
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
3836
import org.springframework.context.annotation.Bean;
3937

4038
import static org.assertj.core.api.Assertions.assertThat;
39+
import static org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration.setupTLS;
4140

4241
public class RestTemplateEurekaClientTests extends BaseCertTests {
4342

@@ -49,7 +48,7 @@ public class RestTemplateEurekaClientTests extends BaseCertTests {
4948

5049
@BeforeAll
5150
public static void setupAll() {
52-
server = startEurekaServer(RestTemplateEurekaClientTests.RestTemplateTestEurekaServer.class);
51+
server = startEurekaServer(TestEurekaServer.class);
5352
service = startService(server, RestTemplateEurekaClientTests.RestTemplateTestApp.class);
5453
// Will use RestTemplate
5554
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
@@ -72,58 +71,35 @@ EurekaClientRunner createEurekaClient() {
7271
@EnableAutoConfiguration
7372
public static class RestTemplateTestApp {
7473

75-
// Want to force reusing exactly the same bean as on production without excluding
76-
// jersey from the classpath
7774
@Bean
7875
public RestTemplateDiscoveryClientOptionalArgs forceRestTemplateDiscoveryClientOptionalArgs(
79-
TlsProperties tlsProperties, DiscoveryClientOptionalArgsConfiguration configuration,
76+
TlsProperties tlsProperties,
8077
EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier)
8178
throws GeneralSecurityException, IOException {
82-
return configuration.restTemplateDiscoveryClientOptionalArgs(tlsProperties,
83-
eurekaClientHttpRequestFactorySupplier, new RestTemplateBuilderObjectProvider());
79+
RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs(
80+
eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new);
81+
setupTLS(result, tlsProperties);
82+
return result;
8483
}
8584

86-
// Want to force reusing exactly the same bean as on production without excluding
87-
// jersey from the classpath
8885
@Bean
8986
public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories(
90-
DiscoveryClientOptionalArgsConfiguration configuration,
9187
RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) {
92-
return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs);
88+
return new RestTemplateTransportClientFactories(discoveryClientOptionalArgs);
89+
}
90+
91+
@Bean
92+
EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier(
93+
RestTemplateTimeoutProperties restTemplateTimeoutProperties) {
94+
return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties);
9395
}
9496

9597
}
9698

9799
@SpringBootConfiguration
98100
@EnableAutoConfiguration
99101
@EnableEurekaServer
100-
public static class RestTemplateTestEurekaServer {
101-
102-
}
103-
104-
private static class RestTemplateBuilderObjectProvider implements ObjectProvider<RestTemplateBuilder> {
105-
106-
private final RestTemplateBuilder builder = new RestTemplateBuilder();
107-
108-
@Override
109-
public RestTemplateBuilder getObject(Object... args) throws BeansException {
110-
return builder;
111-
}
112-
113-
@Override
114-
public RestTemplateBuilder getIfAvailable() throws BeansException {
115-
return builder;
116-
}
117-
118-
@Override
119-
public RestTemplateBuilder getIfUnique() throws BeansException {
120-
return builder;
121-
}
122-
123-
@Override
124-
public RestTemplateBuilder getObject() throws BeansException {
125-
return builder;
126-
}
102+
public static class TestEurekaServer {
127103

128104
}
129105

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2013-2024 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.cloud.netflix.eureka;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
import org.springframework.web.client.RestClient;
21+
22+
/**
23+
* A {@link RestClient}-specific {@link TimeoutProperties} implementation.
24+
*
25+
* @author Olga Maciaszek-Sharma
26+
* @since 4.2.0
27+
*/
28+
@ConfigurationProperties("eureka.client.restclient.timeout")
29+
public class RestClientTimeoutProperties extends TimeoutProperties {
30+
31+
@Override
32+
public String toString() {
33+
return "RestClientTimeoutProperties{" + ", connectTimeout=" + connectTimeout + ", connectRequestTimeout="
34+
+ connectRequestTimeout + ", socketTimeout=" + socketTimeout + '}';
35+
}
36+
37+
}

spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestTemplateTimeoutProperties.java

+7-63
Original file line numberDiff line numberDiff line change
@@ -16,79 +16,23 @@
1616

1717
package org.springframework.cloud.netflix.eureka;
1818

19-
import java.util.Objects;
20-
21-
import org.apache.hc.client5.http.config.RequestConfig;
22-
import org.apache.hc.core5.http.io.SocketConfig;
23-
2419
import org.springframework.boot.context.properties.ConfigurationProperties;
25-
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
20+
import org.springframework.web.client.RestClient;
2621
import org.springframework.web.client.RestTemplate;
2722

2823
/**
29-
* Properties for configuring timeouts used in {@link RestTemplate} required by
30-
* {@link RestTemplateEurekaHttpClient}.
24+
* A {@link RestTemplate}-specific {@link TimeoutProperties} implementation.
3125
*
3226
* @author Jiwon Jeon
3327
* @author Mooyong Lee
28+
* @author Olga Maciaszek-Sharma
3429
* @since 3.1.6
30+
* @deprecated {@link RestTemplate}-based implementation to be removed in favour of
31+
* {@link RestClient}-based implementation.
3532
*/
33+
@Deprecated(forRemoval = true)
3634
@ConfigurationProperties("eureka.client.rest-template-timeout")
37-
public class RestTemplateTimeoutProperties {
38-
39-
/**
40-
* Default values are set to 180000, in keeping with {@link RequestConfig} and
41-
* {@link SocketConfig} defaults.
42-
*/
43-
private int connectTimeout = 180000; // 3 * MINUTES
44-
45-
private int connectRequestTimeout = 180000; // 3 * MINUTES
46-
47-
private int socketTimeout = 180000; // 3 * MINUTES
48-
49-
public int getConnectTimeout() {
50-
return connectTimeout;
51-
}
52-
53-
public int getConnectRequestTimeout() {
54-
return connectRequestTimeout;
55-
}
56-
57-
public int getSocketTimeout() {
58-
return socketTimeout;
59-
}
60-
61-
public void setConnectTimeout(int connectTimeout) {
62-
this.connectTimeout = connectTimeout;
63-
}
64-
65-
public void setConnectRequestTimeout(int connectRequestTimeout) {
66-
this.connectRequestTimeout = connectRequestTimeout;
67-
}
68-
69-
public void setSocketTimeout(int socketTimeout) {
70-
this.socketTimeout = socketTimeout;
71-
}
72-
73-
@Override
74-
public boolean equals(Object o) {
75-
if (this == o) {
76-
return true;
77-
}
78-
if (o == null || getClass() != o.getClass()) {
79-
return false;
80-
}
81-
82-
RestTemplateTimeoutProperties that = (RestTemplateTimeoutProperties) o;
83-
84-
return connectTimeout == that.connectTimeout && connectRequestTimeout == that.connectRequestTimeout
85-
&& socketTimeout == that.socketTimeout;
86-
}
87-
88-
@Override
89-
public int hashCode() {
90-
return Objects.hash(connectTimeout, connectRequestTimeout, socketTimeout);
91-
}
35+
public class RestTemplateTimeoutProperties extends TimeoutProperties {
9236

9337
@Override
9438
public String toString() {

0 commit comments

Comments
 (0)