diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b44059e78..8de18274e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -17,7 +17,7 @@ given the ability to merge pull requests. ## Code of Conduct This project adheres to the Contributor Covenant [code of -conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report +conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/modules/ROOT/partials/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io. ## Code Conventions and Housekeeping diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f9c048e4a..7e6f06596 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -28,6 +28,6 @@ jobs: cache: 'maven' - name: Build with Maven run: ./mvnw clean install -B -U -P sonar - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 with: fail_ci_if_error: false diff --git a/docs/modules/ROOT/pages/spring-cloud-netflix.adoc b/docs/modules/ROOT/pages/spring-cloud-netflix.adoc index 336bba140..e1bc0d282 100755 --- a/docs/modules/ROOT/pages/spring-cloud-netflix.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-netflix.adoc @@ -98,13 +98,18 @@ NOTE: Because of a limitation in Eureka, it is not possible to support per-serve 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. -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.) +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. .application.yml [source,yaml] ---- eureka: client: + restclient: + timeout: + connect-timeout: 5000 + connect-request-timeout: 8000 + socket-timeout: 10000 rest-template-timeout: connect-timeout: 5000 connect-request-timeout: 8000 diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index cdd6374b6..72cc4751f 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -50,6 +50,9 @@ |eureka.client.rest-template-timeout.connect-timeout | `+++180000+++` | Default values are set to 180000, in keeping with {@link RequestConfig} and {@link SocketConfig} defaults. |eureka.client.rest-template-timeout.socket-timeout | `+++180000+++` | |eureka.client.restclient.enabled | `+++false+++` | Enables the use of RestClient for Eureka HTTP Client. +|eureka.client.restclient.timeout.connect-request-timeout | `+++180000+++` | +|eureka.client.restclient.timeout.connect-timeout | `+++180000+++` | Default values are set to 180000, in keeping with {@link RequestConfig} and {@link SocketConfig} defaults. +|eureka.client.restclient.timeout.socket-timeout | `+++180000+++` | |eureka.client.service-url | | Map of availability zone to list of fully qualified URLs to communicate with eureka server. Each value can be a single URL or a comma separated list of alternative locations. Typically the eureka server URLs carry protocol,host,port,context and version information if any. Example: https://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/ The changes are effective at runtime at the next service url refresh cycle as specified by eurekaServiceUrlPollIntervalSeconds. |eureka.client.should-enforce-registration-at-init | `+++false+++` | Indicates whether the client should enforce registration during initialization. Defaults to false. |eureka.client.should-unregister-on-shutdown | `+++true+++` | Indicates whether the client should explicitly unregister itself from the remote server on client shutdown. diff --git a/docs/package.json b/docs/package.json index cff679751..2054ec1c5 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,7 +2,7 @@ "dependencies": { "antora": "3.2.0-alpha.6", "@antora/atlas-extension": "1.0.0-alpha.2", - "@antora/collector-extension": "1.0.0-beta.4", + "@antora/collector-extension": "1.0.0-beta.5", "@asciidoctor/tabs": "1.0.0-beta.6", "@springio/antora-extensions": "1.14.2", "@springio/asciidoctor-extensions": "1.0.0-alpha.14" diff --git a/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientTests.java b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientTests.java index 732edac4d..48ba2da0c 100644 --- a/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientTests.java +++ b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/EurekaClientTests.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.BeforeAll; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration; import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs; import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories; @@ -33,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class EurekaClientTests extends BaseCertTests { - private static final Log log = LogFactory.getLog(EurekaClientTests.class); + private static final Log LOG = LogFactory.getLog(EurekaClientTests.class); static EurekaServerRunner server; @@ -44,7 +43,7 @@ public class EurekaClientTests extends BaseCertTests { server = startEurekaServer(EurekaClientTests.TestEurekaServer.class); service = startService(server, EurekaClientTests.TestApp.class); assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class); - log.info("Successfully asserted that Jersey will be used"); + LOG.info("Successfully asserted that Jersey will be used"); waitForRegistration(() -> new EurekaClientTests().createEurekaClient()); } @@ -59,9 +58,8 @@ public class EurekaClientTests extends BaseCertTests { @Bean public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories( - DiscoveryClientOptionalArgsConfiguration configuration, RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) { - return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs); + return new RestTemplateTransportClientFactories(discoveryClientOptionalArgs); } @Bean diff --git a/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestClientEurekaClientTests.java b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestClientEurekaClientTests.java new file mode 100644 index 000000000..7ad407d81 --- /dev/null +++ b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestClientEurekaClientTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2018-2024 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.cloud.configuration.TlsProperties; +import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; +import org.springframework.cloud.netflix.eureka.http.RestClientDiscoveryClientOptionalArgs; +import org.springframework.cloud.netflix.eureka.http.RestClientTransportClientFactories; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestClient; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration.setupTLS; + +/** + * Tests for verifying TLS setup with {@link RestClientTransportClientFactories}. + * + * @author Olga Maciaszek-Sharma + */ +public class RestClientEurekaClientTests extends BaseCertTests { + + private static final Log LOG = LogFactory.getLog(RestClientEurekaClientTests.class); + + private static EurekaServerRunner server; + + private static EurekaClientRunner service; + + @BeforeAll + public static void setupAll() { + server = startEurekaServer(TestEurekaServer.class); + service = startService(server, TestApp.class); + // Will use RestClient + assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestClientDiscoveryClientOptionalArgs.class); + LOG.info("Successfully asserted that RestClient will be used"); + waitForRegistration(() -> new RestClientEurekaClientTests().createEurekaClient()); + } + + @AfterAll + public static void tearDownAll() { + stopService(service); + stopEurekaServer(server); + } + + @Override + EurekaClientRunner createEurekaClient() { + return new EurekaClientRunner(TestApp.class, server); + } + + @SpringBootConfiguration + @EnableAutoConfiguration + public static class TestApp { + + // Want to force reusing exactly the same bean as on production without excluding + // jersey from the classpath + @Bean + public RestClientDiscoveryClientOptionalArgs forceRestClientDiscoveryClientOptionalArgs( + TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) + throws GeneralSecurityException, IOException { + RestClientDiscoveryClientOptionalArgs result = new RestClientDiscoveryClientOptionalArgs( + eurekaClientHttpRequestFactorySupplier, RestClient::builder); + setupTLS(result, tlsProperties); + return result; + } + + @Bean + public RestClientTransportClientFactories forceRestClientTransportClientFactories( + RestClientDiscoveryClientOptionalArgs discoveryClientOptionalArgs) { + return new RestClientTransportClientFactories(discoveryClientOptionalArgs); + } + + } + + @SpringBootConfiguration + @EnableAutoConfiguration + @EnableEurekaServer + public static class TestEurekaServer { + + } + +} diff --git a/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestTemplateEurekaClientTests.java b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestTemplateEurekaClientTests.java index 8ea1d803b..294ee8b1e 100644 --- a/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestTemplateEurekaClientTests.java +++ b/spring-cloud-netflix-eureka-client-tls-tests/src/test/java/org/springframework/cloud/netflix/eureka/RestTemplateEurekaClientTests.java @@ -24,13 +24,11 @@ import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.configuration.TlsProperties; -import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration; +import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs; import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories; @@ -38,6 +36,7 @@ import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.context.annotation.Bean; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration.setupTLS; public class RestTemplateEurekaClientTests extends BaseCertTests { @@ -49,7 +48,7 @@ public class RestTemplateEurekaClientTests extends BaseCertTests { @BeforeAll public static void setupAll() { - server = startEurekaServer(RestTemplateEurekaClientTests.RestTemplateTestEurekaServer.class); + server = startEurekaServer(TestEurekaServer.class); service = startService(server, RestTemplateEurekaClientTests.RestTemplateTestApp.class); // Will use RestTemplate assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class); @@ -72,24 +71,27 @@ public class RestTemplateEurekaClientTests extends BaseCertTests { @EnableAutoConfiguration public static class RestTemplateTestApp { - // Want to force reusing exactly the same bean as on production without excluding - // jersey from the classpath @Bean public RestTemplateDiscoveryClientOptionalArgs forceRestTemplateDiscoveryClientOptionalArgs( - TlsProperties tlsProperties, DiscoveryClientOptionalArgsConfiguration configuration, + TlsProperties tlsProperties, EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) throws GeneralSecurityException, IOException { - return configuration.restTemplateDiscoveryClientOptionalArgs(tlsProperties, - eurekaClientHttpRequestFactorySupplier, new RestTemplateBuilderObjectProvider()); + RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs( + eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new); + setupTLS(result, tlsProperties); + return result; } - // Want to force reusing exactly the same bean as on production without excluding - // jersey from the classpath @Bean public RestTemplateTransportClientFactories forceRestTemplateTransportClientFactories( - DiscoveryClientOptionalArgsConfiguration configuration, RestTemplateDiscoveryClientOptionalArgs discoveryClientOptionalArgs) { - return configuration.restTemplateTransportClientFactories(discoveryClientOptionalArgs); + return new RestTemplateTransportClientFactories(discoveryClientOptionalArgs); + } + + @Bean + EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( + RestTemplateTimeoutProperties restTemplateTimeoutProperties) { + return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties); } } @@ -97,33 +99,7 @@ public class RestTemplateEurekaClientTests extends BaseCertTests { @SpringBootConfiguration @EnableAutoConfiguration @EnableEurekaServer - public static class RestTemplateTestEurekaServer { - - } - - private static class RestTemplateBuilderObjectProvider implements ObjectProvider { - - private final RestTemplateBuilder builder = new RestTemplateBuilder(); - - @Override - public RestTemplateBuilder getObject(Object... args) throws BeansException { - return builder; - } - - @Override - public RestTemplateBuilder getIfAvailable() throws BeansException { - return builder; - } - - @Override - public RestTemplateBuilder getIfUnique() throws BeansException { - return builder; - } - - @Override - public RestTemplateBuilder getObject() throws BeansException { - return builder; - } + public static class TestEurekaServer { } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestClientTimeoutProperties.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestClientTimeoutProperties.java new file mode 100644 index 000000000..dc60ec8f1 --- /dev/null +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestClientTimeoutProperties.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2024 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.web.client.RestClient; + +/** + * A {@link RestClient}-specific {@link TimeoutProperties} implementation. + * + * @author Olga Maciaszek-Sharma + * @since 4.2.0 + */ +@ConfigurationProperties("eureka.client.restclient.timeout") +public class RestClientTimeoutProperties extends TimeoutProperties { + + @Override + public String toString() { + return "RestClientTimeoutProperties{" + ", connectTimeout=" + connectTimeout + ", connectRequestTimeout=" + + connectRequestTimeout + ", socketTimeout=" + socketTimeout + '}'; + } + +} diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestTemplateTimeoutProperties.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestTemplateTimeoutProperties.java index 15bddb3ba..95f47102c 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestTemplateTimeoutProperties.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/RestTemplateTimeoutProperties.java @@ -16,79 +16,23 @@ package org.springframework.cloud.netflix.eureka; -import java.util.Objects; - -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.core5.http.io.SocketConfig; - import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient; +import org.springframework.web.client.RestClient; import org.springframework.web.client.RestTemplate; /** - * Properties for configuring timeouts used in {@link RestTemplate} required by - * {@link RestTemplateEurekaHttpClient}. + * A {@link RestTemplate}-specific {@link TimeoutProperties} implementation. * * @author Jiwon Jeon * @author Mooyong Lee + * @author Olga Maciaszek-Sharma * @since 3.1.6 + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. */ +@Deprecated(forRemoval = true) @ConfigurationProperties("eureka.client.rest-template-timeout") -public class RestTemplateTimeoutProperties { - - /** - * Default values are set to 180000, in keeping with {@link RequestConfig} and - * {@link SocketConfig} defaults. - */ - private int connectTimeout = 180000; // 3 * MINUTES - - private int connectRequestTimeout = 180000; // 3 * MINUTES - - private int socketTimeout = 180000; // 3 * MINUTES - - public int getConnectTimeout() { - return connectTimeout; - } - - public int getConnectRequestTimeout() { - return connectRequestTimeout; - } - - public int getSocketTimeout() { - return socketTimeout; - } - - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } - - public void setConnectRequestTimeout(int connectRequestTimeout) { - this.connectRequestTimeout = connectRequestTimeout; - } - - public void setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - RestTemplateTimeoutProperties that = (RestTemplateTimeoutProperties) o; - - return connectTimeout == that.connectTimeout && connectRequestTimeout == that.connectRequestTimeout - && socketTimeout == that.socketTimeout; - } - - @Override - public int hashCode() { - return Objects.hash(connectTimeout, connectRequestTimeout, socketTimeout); - } +public class RestTemplateTimeoutProperties extends TimeoutProperties { @Override public String toString() { diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/TimeoutProperties.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/TimeoutProperties.java new file mode 100644 index 000000000..ecfa40f54 --- /dev/null +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/TimeoutProperties.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013-2024 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.netflix.eureka; + +import java.util.Objects; + +import com.netflix.discovery.shared.transport.EurekaHttpClient; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.io.SocketConfig; + +import org.springframework.web.client.RestTemplate; + +/** + * Properties for configuring timeouts used in {@link RestTemplate} required by + * {@link EurekaHttpClient}. + * + * @author Jiwon Jeon + * @author Mooyong Lee + * @author Olga Maciaszek-Sharma + * @since 4.2.0 + */ +public abstract class TimeoutProperties { + + /** + * Default values are set to 180000, in keeping with {@link RequestConfig} and + * {@link SocketConfig} defaults. + */ + protected int connectTimeout = 180000; // 3 * MINUTES + + protected int connectRequestTimeout = 180000; // 3 * MINUTES + + protected int socketTimeout = 180000; // 3 * MINUTES + + public int getConnectTimeout() { + return connectTimeout; + } + + public int getConnectRequestTimeout() { + return connectRequestTimeout; + } + + public int getSocketTimeout() { + return socketTimeout; + } + + public void setConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public void setConnectRequestTimeout(int connectRequestTimeout) { + this.connectRequestTimeout = connectRequestTimeout; + } + + public void setSocketTimeout(int socketTimeout) { + this.socketTimeout = socketTimeout; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + RestTemplateTimeoutProperties that = (RestTemplateTimeoutProperties) o; + + return connectTimeout == that.connectTimeout && connectRequestTimeout == that.connectRequestTimeout + && socketTimeout == that.socketTimeout; + } + + @Override + public int hashCode() { + return Objects.hash(connectTimeout, connectRequestTimeout, socketTimeout); + } + +} diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java index f08ced31d..6e02068cd 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java @@ -38,6 +38,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.configuration.SSLContextFactory; import org.springframework.cloud.configuration.TlsProperties; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties; import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; @@ -51,6 +52,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; /** @@ -60,7 +62,7 @@ import org.springframework.web.reactive.function.client.WebClient; * @author Wonchul Heo */ @Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(RestTemplateTimeoutProperties.class) +@EnableConfigurationProperties({ RestTemplateTimeoutProperties.class, RestClientTimeoutProperties.class }) public class DiscoveryClientOptionalArgsConfiguration { protected static final Log logger = LogFactory.getLog(DiscoveryClientOptionalArgsConfiguration.class); @@ -71,40 +73,8 @@ public class DiscoveryClientOptionalArgsConfiguration { return new TlsProperties(); } - @Bean - @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - @Conditional(RestTemplateEnabledCondition.class) - @ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT) - public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(TlsProperties tlsProperties, - EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, - ObjectProvider restTemplateBuilders) throws GeneralSecurityException, IOException { - if (logger.isInfoEnabled()) { - logger.info("Eureka HTTP Client uses RestTemplate."); - } - RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs( - eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable); - setupTLS(result, tlsProperties); - return result; - } - - @Bean - @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - @Conditional(RestTemplateEnabledCondition.class) - @ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT) - public RestTemplateTransportClientFactories restTemplateTransportClientFactories( - RestTemplateDiscoveryClientOptionalArgs optionalArgs) { - return new RestTemplateTransportClientFactories(optionalArgs); - } - - @Bean - @ConditionalOnMissingBean - @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") - EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( - RestTemplateTimeoutProperties restTemplateTimeoutProperties) { - return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties); - } - - private static void setupTLS(AbstractDiscoveryClientOptionalArgs args, TlsProperties properties) + // Visible for tests + public static void setupTLS(AbstractDiscoveryClientOptionalArgs args, TlsProperties properties) throws GeneralSecurityException, IOException { if (properties.isEnabled()) { SSLContextFactory factory = new SSLContextFactory(properties); @@ -112,8 +82,49 @@ public class DiscoveryClientOptionalArgsConfiguration { } } + /** + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. + */ @Configuration(proxyBeanMethods = false) - @Conditional(JerseyClientPresentAndEnabledCondition.class) + @Conditional(OnRestTemplatePresentAndEnabledCondition.class) + @Deprecated + static class RestTemplateConfiguration { + + @Bean + @ConditionalOnMissingBean + EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( + RestTemplateTimeoutProperties restTemplateTimeoutProperties) { + return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties); + } + + @Bean + @ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, + search = SearchStrategy.CURRENT) + public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs( + TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + ObjectProvider restTemplateBuilders) throws GeneralSecurityException, IOException { + if (logger.isInfoEnabled()) { + logger.info("Eureka HTTP Client uses RestTemplate."); + } + RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs( + eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable); + setupTLS(result, tlsProperties); + return result; + } + + @Bean + @ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT) + public RestTemplateTransportClientFactories restTemplateTransportClientFactories( + RestTemplateDiscoveryClientOptionalArgs optionalArgs) { + return new RestTemplateTransportClientFactories(optionalArgs); + } + + } + + @Configuration(proxyBeanMethods = false) + @Conditional(OnJerseyClientPresentAndEnabledCondition.class) @ConditionalOnBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT) static class DiscoveryClientOptionalArgsTlsConfiguration { @@ -127,7 +138,8 @@ public class DiscoveryClientOptionalArgsConfiguration { } - @Conditional(JerseyClientNotPresentOrNotEnabledCondition.class) + @Configuration(proxyBeanMethods = false) + @Conditional(OnJerseyClientNotPresentOrNotEnabledCondition.class) @ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient") @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true") protected static class WebClientConfiguration { @@ -156,8 +168,8 @@ public class DiscoveryClientOptionalArgsConfiguration { } - @Configuration - @Conditional(JerseyClientNotPresentOrNotEnabledCondition.class) + @Configuration(proxyBeanMethods = false) + @Conditional(OnJerseyClientNotPresentOrNotEnabledCondition.class) @ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient") @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true") protected static class WebClientNotFoundConfiguration { @@ -170,20 +182,30 @@ public class DiscoveryClientOptionalArgsConfiguration { } - @ConditionalOnClass(name = "org.springframework.web.client.RestClient") - @Conditional(RestClientEnabledCondition.class) + @Configuration(proxyBeanMethods = false) + @Conditional(OnRestClientPresentAndEnabledCondition.class) protected static class RestClientConfiguration { + @Bean + @ConditionalOnMissingBean + EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( + RestClientTimeoutProperties restClientTimeoutProperties) { + return new DefaultEurekaClientHttpRequestFactorySupplier(restClientTimeoutProperties); + } + @Bean @ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT) public RestClientDiscoveryClientOptionalArgs restClientDiscoveryClientOptionalArgs(TlsProperties tlsProperties, - ObjectProvider builder) throws GeneralSecurityException, IOException { + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + ObjectProvider restClientBuilderProvider) + throws GeneralSecurityException, IOException { if (logger.isInfoEnabled()) { logger.info("Eureka HTTP Client uses RestClient."); } RestClientDiscoveryClientOptionalArgs result = new RestClientDiscoveryClientOptionalArgs( - builder::getIfAvailable); + eurekaClientHttpRequestFactorySupplier, + () -> restClientBuilderProvider.getIfAvailable(RestClient::builder)); setupTLS(result, tlsProperties); return result; } @@ -191,15 +213,15 @@ public class DiscoveryClientOptionalArgsConfiguration { @Bean @ConditionalOnMissingBean(value = TransportClientFactories.class, search = SearchStrategy.CURRENT) public RestClientTransportClientFactories restClientTransportClientFactories( - ObjectProvider builder) { - return new RestClientTransportClientFactories(builder::getIfAvailable); + RestClientDiscoveryClientOptionalArgs args) { + return new RestClientTransportClientFactories(args); } } - static class JerseyClientPresentAndEnabledCondition extends AllNestedConditions { + static class OnJerseyClientPresentAndEnabledCondition extends AllNestedConditions { - JerseyClientPresentAndEnabledCondition() { + OnJerseyClientPresentAndEnabledCondition() { super(ConfigurationPhase.REGISTER_BEAN); } @@ -215,9 +237,9 @@ public class DiscoveryClientOptionalArgsConfiguration { } - static class JerseyClientNotPresentOrNotEnabledCondition extends AnyNestedCondition { + static class OnJerseyClientNotPresentOrNotEnabledCondition extends AnyNestedCondition { - JerseyClientNotPresentOrNotEnabledCondition() { + OnJerseyClientNotPresentOrNotEnabledCondition() { super(ConfigurationPhase.REGISTER_BEAN); } @@ -233,13 +255,23 @@ public class DiscoveryClientOptionalArgsConfiguration { } - static class RestTemplateEnabledCondition extends AllNestedConditions { + /** + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. + */ + @Deprecated(forRemoval = true) + static class OnRestTemplatePresentAndEnabledCondition extends AllNestedConditions { - RestTemplateEnabledCondition() { + OnRestTemplatePresentAndEnabledCondition() { super(ConfigurationPhase.REGISTER_BEAN); } - @Conditional(JerseyClientNotPresentOrNotEnabledCondition.class) + @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") + static class OnRestTemplatePresent { + + } + + @Conditional(OnJerseyClientNotPresentOrNotEnabledCondition.class) static class OnJerseyClientNotPresentOrNotEnabled { } @@ -257,13 +289,18 @@ public class DiscoveryClientOptionalArgsConfiguration { } - static class RestClientEnabledCondition extends AllNestedConditions { + static class OnRestClientPresentAndEnabledCondition extends AllNestedConditions { - RestClientEnabledCondition() { + OnRestClientPresentAndEnabledCondition() { super(ConfigurationPhase.REGISTER_BEAN); } - @Conditional(JerseyClientNotPresentOrNotEnabledCondition.class) + @ConditionalOnClass(name = "org.springframework.web.client.RestClient") + static class OnRestClientPresent { + + } + + @Conditional(OnJerseyClientNotPresentOrNotEnabledCondition.class) static class OnJerseyClientNotPresentOrNotEnabled { } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapConfiguration.java index b1048a508..13cbb8cae 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapConfiguration.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapConfiguration.java @@ -27,7 +27,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -35,6 +34,7 @@ import org.springframework.cloud.config.client.ConfigServerInstanceProvider; import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator; import org.springframework.cloud.configuration.TlsProperties; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties; import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; @@ -50,6 +50,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.lang.Nullable; import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; /** @@ -59,11 +60,12 @@ import org.springframework.web.reactive.function.client.WebClient; * @author Dave Syer * @author Armin Krezovic * @author Wonchul Heo + * @author Olga Maciaszek-Sharma */ @ConditionalOnClass(ConfigServicePropertySourceLocator.class) @Conditional(EurekaConfigServerBootstrapConfiguration.EurekaConfigServerBootstrapCondition.class) @Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(RestTemplateTimeoutProperties.class) +@EnableConfigurationProperties({ RestTemplateTimeoutProperties.class, RestClientTimeoutProperties.class }) public class EurekaConfigServerBootstrapConfiguration { @Bean @@ -72,31 +74,70 @@ public class EurekaConfigServerBootstrapConfiguration { return new EurekaClientConfigBean(); } - @Bean - @ConditionalOnMissingBean(EurekaHttpClient.class) - @Conditional(RestTemplateEnabledCondition.class) - public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(EurekaClientConfigBean config, - Environment env, @Nullable TlsProperties properties, - EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, - ObjectProvider restTemplateBuilders) { - return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory(properties, - eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable) - .newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env)); - } - - @Bean - @ConditionalOnMissingBean - EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( - RestTemplateTimeoutProperties restTemplateTimeoutProperties) { - return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties); - } - @Bean public ConfigServerInstanceProvider.Function eurekaConfigServerInstanceProvider(EurekaHttpClient client, EurekaClientConfig config) { return new EurekaConfigServerInstanceProvider(client, config)::getInstances; } + /** + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. + */ + @Configuration(proxyBeanMethods = false) + @Conditional(RestTemplateConfiguration.OnRestTemplatePresentAndEnabledCondition.class) + @Deprecated + static class RestTemplateConfiguration { + + @Bean + @ConditionalOnMissingBean(EurekaHttpClient.class) + public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(EurekaClientConfigBean config, + Environment env, @Nullable TlsProperties properties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + ObjectProvider restTemplateBuilders) { + return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory(properties, + eurekaClientHttpRequestFactorySupplier, restTemplateBuilders::getIfAvailable) + .newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env)); + } + + @Bean + @ConditionalOnMissingBean + EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( + RestTemplateTimeoutProperties restTemplateTimeoutProperties) { + return new DefaultEurekaClientHttpRequestFactorySupplier(restTemplateTimeoutProperties); + } + + /** + * @deprecated {@link RestTemplate}-based implementation to be removed in favour + * of {@link RestClient}-based implementation. + */ + @Deprecated(forRemoval = true) + static class OnRestTemplatePresentAndEnabledCondition extends AllNestedConditions { + + OnRestTemplatePresentAndEnabledCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnClass(name = "org.springframework.web.client.RestTemplate") + static class OnRestTemplatePresent { + + } + + @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true, + havingValue = "false") + static class OnWebClientDisabled { + + } + + @ConditionalOnProperty(prefix = "eureka.client", name = "restclient.enabled", havingValue = "false") + static class OnRestClientDisabled { + + } + + } + + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient") @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true") @@ -114,55 +155,50 @@ public class EurekaConfigServerBootstrapConfiguration { } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(name = "org.springframework.web.client.RestClient") - @Conditional(RestClientEnabledCondition.class) - @ImportAutoConfiguration(RestClientAutoConfiguration.class) - protected static class RestClientConfiguration { + @Conditional(RestClientConfiguration.OnRestClientPresentAndEnabledCondition.class) + static class RestClientConfiguration { @Bean @ConditionalOnMissingBean(EurekaHttpClient.class) public RestClientEurekaHttpClient configDiscoveryRestClientEurekaHttpClient(EurekaClientConfigBean config, - ObjectProvider builder, Environment env) { - return (RestClientEurekaHttpClient) new RestClientTransportClientFactory(builder::getIfAvailable) + @Nullable TlsProperties properties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + ObjectProvider restClientBuilderProvider, Environment env) { + return (RestClientEurekaHttpClient) new RestClientTransportClientFactory(properties, + eurekaClientHttpRequestFactorySupplier, + () -> restClientBuilderProvider.getIfAvailable(RestClient::builder)) .newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, env)); } - } - - static class RestTemplateEnabledCondition extends AllNestedConditions { - - RestTemplateEnabledCondition() { - super(ConfigurationPhase.REGISTER_BEAN); + @Bean + @ConditionalOnMissingBean + EurekaClientHttpRequestFactorySupplier defaultEurekaClientHttpRequestFactorySupplier( + RestClientTimeoutProperties restClientTimeoutProperties) { + return new DefaultEurekaClientHttpRequestFactorySupplier(restClientTimeoutProperties); } - @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true, - havingValue = "false") - static class OnWebClientDisabled { + static class OnRestClientPresentAndEnabledCondition extends AllNestedConditions { - } + OnRestClientPresentAndEnabledCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } - @ConditionalOnProperty(prefix = "eureka.client", name = "restclient.enabled", havingValue = "false") - static class OnRestClientDisabled { + @ConditionalOnClass(name = "org.springframework.web.client.RestClient") + static class OnRestClientPresentCondition { - } + } - } + @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true, + havingValue = "false") + static class OnWebClientDisabled { - static class RestClientEnabledCondition extends AllNestedConditions { + } - RestClientEnabledCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } + @ConditionalOnProperty(prefix = "eureka.client", name = "restclient.enabled", matchIfMissing = true, + havingValue = "true") + static class OnRestClientEnabled { - @ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true, - havingValue = "false") - static class OnWebClientDisabled { - - } - - @ConditionalOnProperty(prefix = "eureka.client", name = "restclient.enabled", matchIfMissing = true, - havingValue = "true") - static class OnRestClientEnabled { + } } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapper.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapper.java index fdde151f9..7892754ca 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapper.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 the original author or authors. + * Copyright 2013-2024 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. @@ -30,9 +30,10 @@ import org.springframework.cloud.config.client.ConfigServerConfigDataLocationRes import org.springframework.cloud.config.client.ConfigServerInstanceProvider; import org.springframework.cloud.configuration.TlsProperties; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; -import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactory; +import org.springframework.cloud.netflix.eureka.http.RestClientTransportClientFactory; import org.springframework.util.ClassUtils; public class EurekaConfigServerBootstrapper implements BootstrapRegistryInitializer { @@ -57,10 +58,10 @@ public class EurekaConfigServerBootstrapper implements BootstrapRegistryInitiali return (id) -> Collections.emptyList(); } EurekaClientConfigBean config = context.get(EurekaClientConfigBean.class); - EurekaHttpClient httpClient = new RestTemplateTransportClientFactory( + EurekaHttpClient httpClient = new RestClientTransportClientFactory( context.getOrElse(TlsProperties.class, null), context.getOrElse(EurekaClientHttpRequestFactorySupplier.class, - new DefaultEurekaClientHttpRequestFactorySupplier())) + new DefaultEurekaClientHttpRequestFactorySupplier(new RestClientTimeoutProperties()))) .newClient(HostnameBasedUrlRandomizer.randomEndpoint(config, getPropertyResolver(context))); return new EurekaConfigServerInstanceProvider(httpClient, config)::getInstances; }); diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/DefaultEurekaClientHttpRequestFactorySupplier.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/DefaultEurekaClientHttpRequestFactorySupplier.java index bc6b092d1..ab368a522 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/DefaultEurekaClientHttpRequestFactorySupplier.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/DefaultEurekaClientHttpRequestFactorySupplier.java @@ -32,6 +32,7 @@ import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.util.Timeout; import org.springframework.cloud.netflix.eureka.RestTemplateTimeoutProperties; +import org.springframework.cloud.netflix.eureka.TimeoutProperties; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.lang.Nullable; @@ -47,29 +48,38 @@ import org.springframework.lang.Nullable; */ public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClientHttpRequestFactorySupplier { - private final RestTemplateTimeoutProperties restTemplateTimeoutProperties; + private final TimeoutProperties timeoutProperties; /** * @deprecated in favour of - * {@link DefaultEurekaClientHttpRequestFactorySupplier#DefaultEurekaClientHttpRequestFactorySupplier(RestTemplateTimeoutProperties)} + * {@link DefaultEurekaClientHttpRequestFactorySupplier#DefaultEurekaClientHttpRequestFactorySupplier(TimeoutProperties)} */ @Deprecated(forRemoval = true) public DefaultEurekaClientHttpRequestFactorySupplier() { - this.restTemplateTimeoutProperties = new RestTemplateTimeoutProperties(); + this.timeoutProperties = new RestTemplateTimeoutProperties(); } - public DefaultEurekaClientHttpRequestFactorySupplier(RestTemplateTimeoutProperties restTemplateTimeoutProperties) { - this.restTemplateTimeoutProperties = restTemplateTimeoutProperties; + /** + * @deprecated in favour of + * {@link DefaultEurekaClientHttpRequestFactorySupplier#DefaultEurekaClientHttpRequestFactorySupplier(TimeoutProperties)} + */ + @Deprecated(forRemoval = true) + public DefaultEurekaClientHttpRequestFactorySupplier(RestTemplateTimeoutProperties timeoutProperties) { + this.timeoutProperties = timeoutProperties; + } + + public DefaultEurekaClientHttpRequestFactorySupplier(TimeoutProperties timeoutProperties) { + this.timeoutProperties = timeoutProperties; } @Override public ClientHttpRequestFactory get(SSLContext sslContext, @Nullable HostnameVerifier hostnameVerifier) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); - if (sslContext != null || hostnameVerifier != null || restTemplateTimeoutProperties != null) { - httpClientBuilder.setConnectionManager( - buildConnectionManager(sslContext, hostnameVerifier, restTemplateTimeoutProperties)); + if (sslContext != null || hostnameVerifier != null || timeoutProperties != null) { + httpClientBuilder + .setConnectionManager(buildConnectionManager(sslContext, hostnameVerifier, timeoutProperties)); } - if (restTemplateTimeoutProperties != null) { + if (timeoutProperties != null) { httpClientBuilder.setDefaultRequestConfig(buildRequestConfig()); } @@ -80,7 +90,7 @@ public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClie } private HttpClientConnectionManager buildConnectionManager(SSLContext sslContext, HostnameVerifier hostnameVerifier, - RestTemplateTimeoutProperties restTemplateTimeoutProperties) { + TimeoutProperties restTemplateTimeoutProperties) { PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder .create(); SSLConnectionSocketFactoryBuilder sslConnectionSocketFactoryBuilder = SSLConnectionSocketFactoryBuilder @@ -102,9 +112,9 @@ public class DefaultEurekaClientHttpRequestFactorySupplier implements EurekaClie private RequestConfig buildRequestConfig() { return RequestConfig.custom() - .setConnectTimeout(Timeout.of(restTemplateTimeoutProperties.getConnectTimeout(), TimeUnit.MILLISECONDS)) + .setConnectTimeout(Timeout.of(timeoutProperties.getConnectTimeout(), TimeUnit.MILLISECONDS)) .setConnectionRequestTimeout( - Timeout.of(restTemplateTimeoutProperties.getConnectRequestTimeout(), TimeUnit.MILLISECONDS)) + Timeout.of(timeoutProperties.getConnectRequestTimeout(), TimeUnit.MILLISECONDS)) .build(); } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaHttpClientUtils.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaHttpClientUtils.java index a45213c30..47ea010f8 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaHttpClientUtils.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaHttpClientUtils.java @@ -18,6 +18,9 @@ package org.springframework.cloud.netflix.eureka.http; import java.net.URI; import java.net.URISyntaxException; +import java.util.Optional; + +import javax.net.ssl.SSLContext; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -36,6 +39,8 @@ import com.netflix.discovery.converters.jackson.serializer.InstanceInfoJsonBeanS import com.netflix.discovery.shared.Applications; import com.netflix.discovery.shared.transport.EurekaHttpClient; +import org.springframework.cloud.configuration.SSLContextFactory; +import org.springframework.cloud.configuration.TlsProperties; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.lang.Nullable; @@ -44,6 +49,7 @@ import org.springframework.lang.Nullable; * * @author Daniel Lavoie * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.2.0 */ final class EurekaHttpClientUtils { @@ -123,6 +129,18 @@ final class EurekaHttpClientUtils { return null; } + static Optional context(TlsProperties properties) { + if (properties == null || !properties.isEnabled()) { + return Optional.empty(); + } + try { + return Optional.of(new SSLContextFactory(properties).createSSLContext()); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } + record UserInfo(String username, String password) { } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientDiscoveryClientOptionalArgs.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientDiscoveryClientOptionalArgs.java index 93f94a18d..238e71d6f 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientDiscoveryClientOptionalArgs.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientDiscoveryClientOptionalArgs.java @@ -28,11 +28,28 @@ import org.springframework.web.client.RestClient; * supplying {@link ClientRequestFilter}. * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.2.0 */ public class RestClientDiscoveryClientOptionalArgs extends AbstractDiscoveryClientOptionalArgs { - public RestClientDiscoveryClientOptionalArgs(Supplier builder) { + private final EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier; + + private final Supplier restClientBuilderSupplier; + + public RestClientDiscoveryClientOptionalArgs( + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + Supplier restClientBuilderSupplier) { + this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier; + this.restClientBuilderSupplier = restClientBuilderSupplier; + } + + EurekaClientHttpRequestFactorySupplier getEurekaClientHttpRequestFactorySupplier() { + return eurekaClientHttpRequestFactorySupplier; + } + + Supplier getRestClientBuilderSupplier() { + return restClientBuilderSupplier; } } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactories.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactories.java index d1596bf25..cdcbfe5b9 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactories.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactories.java @@ -18,7 +18,6 @@ package org.springframework.cloud.netflix.eureka.http; import java.util.Collection; import java.util.Optional; -import java.util.function.Supplier; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; @@ -28,31 +27,32 @@ import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.shared.transport.TransportClientFactory; import com.netflix.discovery.shared.transport.jersey.TransportClientFactories; -import org.springframework.web.client.RestClient; - /** * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.2.0 */ public class RestClientTransportClientFactories implements TransportClientFactories { - private final Supplier builder; + private final RestClientDiscoveryClientOptionalArgs args; - public RestClientTransportClientFactories(Supplier builder) { - this.builder = builder; + public RestClientTransportClientFactories(RestClientDiscoveryClientOptionalArgs args) { + this.args = args; } @Override public TransportClientFactory newTransportClientFactory(EurekaClientConfig clientConfig, Collection additionalFilters, InstanceInfo myInstanceInfo) { - return new RestClientTransportClientFactory(builder); + return new RestClientTransportClientFactory(args.getSSLContext(), args.getHostnameVerifier(), + args.getEurekaClientHttpRequestFactorySupplier(), args.getRestClientBuilderSupplier()); } @Override public TransportClientFactory newTransportClientFactory(final EurekaClientConfig clientConfig, final Collection additionalFilters, final InstanceInfo myInstanceInfo, final Optional sslContext, final Optional hostnameVerifier) { - return new RestClientTransportClientFactory(builder); + return new RestClientTransportClientFactory(args.getSSLContext(), args.getHostnameVerifier(), + args.getEurekaClientHttpRequestFactorySupplier(), args.getRestClientBuilderSupplier()); } } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactory.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactory.java index 9fac73a11..8de8dea51 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactory.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactory.java @@ -16,19 +16,26 @@ package org.springframework.cloud.netflix.eureka.http; +import java.util.Optional; import java.util.function.Supplier; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + import com.netflix.discovery.shared.resolver.EurekaEndpoint; import com.netflix.discovery.shared.transport.EurekaHttpClient; import com.netflix.discovery.shared.transport.TransportClientFactory; +import org.springframework.cloud.configuration.TlsProperties; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; +import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.web.client.RestClient; import org.springframework.web.util.UriComponentsBuilder; +import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.context; import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.extractUserInfo; import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.mappingJacksonHttpMessageConverter; @@ -38,20 +45,49 @@ import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtil * deserialization. * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma * @since 4.2.0 */ public class RestClientTransportClientFactory implements TransportClientFactory { + private final Optional sslContext; + + private final Optional hostnameVerifier; + + private final EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier; + private final Supplier builderSupplier; - public RestClientTransportClientFactory(Supplier builderSupplier) { + public RestClientTransportClientFactory(Optional sslContext, + Optional hostnameVerifier, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + Supplier builderSupplier) { + this.sslContext = sslContext; + this.hostnameVerifier = hostnameVerifier; + this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier; this.builderSupplier = builderSupplier; } + public RestClientTransportClientFactory(TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + Supplier builderSupplier) { + this(context(tlsProperties), Optional.empty(), eurekaClientHttpRequestFactorySupplier, builderSupplier); + } + + public RestClientTransportClientFactory(TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) { + this(tlsProperties, eurekaClientHttpRequestFactorySupplier, RestClient::builder); + } + @Override public EurekaHttpClient newClient(EurekaEndpoint endpoint) { // we want a copy to modify. Don't change the original final RestClient.Builder builder = builderSupplier.get().clone(); + + ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier + .get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null)); + + builder.requestFactory(requestFactory); setUrl(builder, endpoint.getServiceUrl()); builder.messageConverters(converters -> converters.add(0, mappingJacksonHttpMessageConverter())); @@ -69,6 +105,10 @@ public class RestClientTransportClientFactory implements TransportClientFactory return new RestClientEurekaHttpClient(builder.build()); } + @Override + public void shutdown() { + } + private static void setUrl(RestClient.Builder builder, String serviceUrl) { final String url = UriComponentsBuilder.fromUriString(serviceUrl).userInfo(null).toUriString(); @@ -79,8 +119,4 @@ public class RestClientTransportClientFactory implements TransportClientFactory builder.baseUrl(url); } - @Override - public void shutdown() { - } - } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java index 663afb6ae..13b253f92 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java @@ -21,11 +21,16 @@ import java.util.function.Supplier; import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; /** * @author Daniel Lavoie * @author Armin Krezovic + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. */ +@Deprecated public class RestTemplateDiscoveryClientOptionalArgs extends AbstractDiscoveryClientOptionalArgs { protected final EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier; diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java index 7677f079d..81f730205 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java @@ -38,6 +38,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestClient; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @@ -46,7 +47,10 @@ import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEureka /** * @author Daniel Lavoie * @author Václav Plic + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. */ +@Deprecated(forRemoval = true) public class RestTemplateEurekaHttpClient implements EurekaHttpClient { private final RestTemplate restTemplate; diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java index 09f4c1c0a..b3167752f 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java @@ -27,10 +27,16 @@ import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.shared.transport.TransportClientFactory; import com.netflix.discovery.shared.transport.jersey.TransportClientFactories; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; + /** * @author Daniel Lavoie * @author Armin Krezovic + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. */ +@Deprecated(forRemoval = true) public class RestTemplateTransportClientFactories implements TransportClientFactories { private final RestTemplateDiscoveryClientOptionalArgs args; @@ -42,16 +48,16 @@ public class RestTemplateTransportClientFactories implements TransportClientFact @Override public TransportClientFactory newTransportClientFactory(EurekaClientConfig clientConfig, Collection additionalFilters, InstanceInfo myInstanceInfo) { - return new RestTemplateTransportClientFactory(this.args.getSSLContext(), this.args.getHostnameVerifier(), - this.args.eurekaClientHttpRequestFactorySupplier, this.args.restTemplateBuilderSupplier); + return new RestTemplateTransportClientFactory(args.getSSLContext(), args.getHostnameVerifier(), + args.eurekaClientHttpRequestFactorySupplier, args.restTemplateBuilderSupplier); } @Override public TransportClientFactory newTransportClientFactory(final EurekaClientConfig clientConfig, final Collection additionalFilters, final InstanceInfo myInstanceInfo, final Optional sslContext, final Optional hostnameVerifier) { - return new RestTemplateTransportClientFactory(this.args.getSSLContext(), this.args.getHostnameVerifier(), - this.args.eurekaClientHttpRequestFactorySupplier, this.args.restTemplateBuilderSupplier); + return new RestTemplateTransportClientFactory(args.getSSLContext(), args.getHostnameVerifier(), + args.eurekaClientHttpRequestFactorySupplier, args.restTemplateBuilderSupplier); } } diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java index f554781e1..9c15ecfe7 100644 --- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java +++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java @@ -27,7 +27,6 @@ import com.netflix.discovery.shared.transport.EurekaHttpClient; import com.netflix.discovery.shared.transport.TransportClientFactory; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.cloud.configuration.SSLContextFactory; import org.springframework.cloud.configuration.TlsProperties; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; @@ -35,9 +34,11 @@ import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestClient; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.context; import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.extractUserInfo; import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtils.mappingJacksonHttpMessageConverter; @@ -49,7 +50,11 @@ import static org.springframework.cloud.netflix.eureka.http.EurekaHttpClientUtil * @author Daniel Lavoie * @author Armin Krezovic * @author Wonchul Heo + * @author Olga Maciaszek-Sharma + * @deprecated {@link RestTemplate}-based implementation to be removed in favour of + * {@link RestClient}-based implementation. */ +@Deprecated(forRemoval = true) public class RestTemplateTransportClientFactory implements TransportClientFactory { private final Optional sslContext; @@ -60,32 +65,6 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor private final Supplier restTemplateBuilderSupplier; - public RestTemplateTransportClientFactory(TlsProperties tlsProperties, - EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, - Supplier restTemplateBuilderSupplier) { - this.sslContext = context(tlsProperties); - this.hostnameVerifier = Optional.empty(); - this.eurekaClientHttpRequestFactorySupplier = eurekaClientHttpRequestFactorySupplier; - this.restTemplateBuilderSupplier = restTemplateBuilderSupplier; - } - - public RestTemplateTransportClientFactory(TlsProperties tlsProperties, - EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) { - this(tlsProperties, eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new); - } - - private Optional context(TlsProperties properties) { - if (properties == null || !properties.isEnabled()) { - return Optional.empty(); - } - try { - return Optional.of(new SSLContextFactory(properties).createSSLContext()); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - } - public RestTemplateTransportClientFactory(Optional sslContext, Optional hostnameVerifier, EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, @@ -96,6 +75,18 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor this.restTemplateBuilderSupplier = restTemplateBuilderSupplier; } + public RestTemplateTransportClientFactory(TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier, + Supplier restTemplateBuilderSupplier) { + this(context(tlsProperties), Optional.empty(), eurekaClientHttpRequestFactorySupplier, + restTemplateBuilderSupplier); + } + + public RestTemplateTransportClientFactory(TlsProperties tlsProperties, + EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) { + this(tlsProperties, eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new); + } + public RestTemplateTransportClientFactory(Optional sslContext, Optional hostnameVerifier, EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) { @@ -103,6 +94,11 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor this(sslContext, hostnameVerifier, eurekaClientHttpRequestFactorySupplier, RestTemplateBuilder::new); } + // Visible for testing + /** + * @deprecated pass the default values while initialising object in test classes. + */ + @Deprecated(forRemoval = true) public RestTemplateTransportClientFactory() { this(Optional.empty(), Optional.empty(), new DefaultEurekaClientHttpRequestFactorySupplier()); } diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientEurekaHttpClientTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientEurekaHttpClientTests.java index dfac061ed..a9fafc0cc 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientEurekaHttpClientTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientEurekaHttpClientTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.netflix.eureka.http; +import java.util.Optional; + import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; import com.netflix.discovery.shared.resolver.DefaultEndpoint; import org.junit.jupiter.api.BeforeEach; @@ -26,11 +28,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; import org.springframework.test.annotation.DirtiesContext; import org.springframework.web.client.RestClient; /** + * Tests for {@link RestClientEurekaHttpClient}. + * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma */ @SpringBootTest(classes = EurekaServerMockApplication.class, properties = { "debug=true", "security.basic.enabled=true", "eureka.client.fetch-registry=false", @@ -47,7 +53,9 @@ class RestClientEurekaHttpClientTests extends AbstractEurekaHttpClientTests { @BeforeEach void setup() { - eurekaHttpClient = new RestClientTransportClientFactory(RestClient::builder) + eurekaHttpClient = new RestClientTransportClientFactory(Optional.empty(), Optional.empty(), + new DefaultEurekaClientHttpRequestFactorySupplier(new RestClientTimeoutProperties()), + RestClient::builder) .newClient(new DefaultEndpoint(serviceUrl)); EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils); diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactoryTests.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactoryTests.java index 0c4269475..067b272c0 100644 --- a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactoryTests.java +++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestClientTransportClientFactoryTests.java @@ -16,18 +16,24 @@ package org.springframework.cloud.netflix.eureka.http; +import java.util.Optional; + import com.netflix.discovery.shared.resolver.DefaultEndpoint; import com.netflix.discovery.shared.transport.EurekaHttpClient; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; import org.springframework.web.client.RestClient; import static org.assertj.core.api.Assertions.assertThat; /** + * Tests for {@link RestClientTransportClientFactory}. + * * @author Wonchul Heo + * @author Olga Maciaszek-Sharma */ class RestClientTransportClientFactoryTests { @@ -35,7 +41,9 @@ class RestClientTransportClientFactoryTests { @BeforeEach void setup() { - transportClientFactory = new RestClientTransportClientFactory(RestClient::builder); + transportClientFactory = new RestClientTransportClientFactory(Optional.empty(), Optional.empty(), + new DefaultEurekaClientHttpRequestFactorySupplier(new RestClientTimeoutProperties()), + RestClient::builder); } @Test