Allow disabling the under the hood use of JerseyClient with Eureka Client. Fixes gh-4185.
This commit is contained in:
@@ -294,6 +294,8 @@ The following example shows the dependencies you need to add:
|
||||
</dependencies>
|
||||
----
|
||||
|
||||
If you have `JerseyClient` on the classpath but do not wish to use it in your `EuerekaClient`, make sure to set `eureka.client.jersey.enabled` to `false`.
|
||||
|
||||
=== Alternatives to the Native Netflix EurekaClient
|
||||
|
||||
You need not use the raw Netflix `EurekaClient`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -33,9 +33,9 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
abstract class BaseCertTest {
|
||||
abstract class BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(BaseCertTest.class);
|
||||
private static final Log log = LogFactory.getLog(BaseCertTests.class);
|
||||
|
||||
protected static final String KEY_STORE_PASSWORD = "test-key-store-password";
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class BaseCertTest {
|
||||
|
||||
protected static File wrongClientCert;
|
||||
|
||||
protected BaseCertTest() {
|
||||
protected BaseCertTests() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -27,7 +27,7 @@ import org.junit.runners.Suite;
|
||||
* already shutdown.
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({ EurekaClientTest.class, RestTemplateEurekaClientTest.class })
|
||||
@Suite.SuiteClasses({ EurekaClientTests.class, RestTemplateEurekaClientTests.class })
|
||||
public class EurekaClientSuite {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -27,9 +27,9 @@ import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class EurekaClientTest extends BaseCertTest {
|
||||
public class EurekaClientTests extends BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(EurekaClientTest.class);
|
||||
private static final Log log = LogFactory.getLog(EurekaClientTests.class);
|
||||
|
||||
static EurekaServerRunner server;
|
||||
|
||||
@@ -37,11 +37,11 @@ public class EurekaClientTest extends BaseCertTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupAll() {
|
||||
server = startEurekaServer(EurekaClientTest.TestEurekaServer.class);
|
||||
service = startService(server, EurekaClientTest.TestApp.class);
|
||||
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");
|
||||
waitForRegistration(() -> new EurekaClientTest().createEurekaClient());
|
||||
waitForRegistration(() -> new EurekaClientTests().createEurekaClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2022 the original author or authors.
|
||||
* 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.
|
||||
@@ -38,9 +38,9 @@ import org.springframework.context.annotation.Bean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
public class RestTemplateEurekaClientTests extends BaseCertTests {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RestTemplateEurekaClientTest.class);
|
||||
private static final Log log = LogFactory.getLog(RestTemplateEurekaClientTests.class);
|
||||
|
||||
private static EurekaServerRunner server;
|
||||
|
||||
@@ -48,12 +48,12 @@ public class RestTemplateEurekaClientTest extends BaseCertTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupAll() {
|
||||
server = startEurekaServer(RestTemplateEurekaClientTest.RestTemplateTestEurekaServer.class);
|
||||
service = startService(server, RestTemplateEurekaClientTest.RestTemplateTestApp.class);
|
||||
server = startEurekaServer(RestTemplateEurekaClientTests.RestTemplateTestEurekaServer.class);
|
||||
service = startService(server, RestTemplateEurekaClientTests.RestTemplateTestApp.class);
|
||||
// Will use RestTemplate
|
||||
assertThat(service.discoveryClientOptionalArgs()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
log.info("Successfully asserted that RestTemplate will be used");
|
||||
waitForRegistration(() -> new RestTemplateEurekaClientTest().createEurekaClient());
|
||||
waitForRegistration(() -> new RestTemplateEurekaClientTests().createEurekaClient());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -26,6 +26,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -45,12 +47,14 @@ import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClient
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientTransportClientFactories;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
* @author Armin Krezovic
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties.class)
|
||||
@@ -66,7 +70,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
@@ -82,7 +86,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", matchIfMissing = true,
|
||||
havingValue = "false")
|
||||
@@ -108,7 +112,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientPresentAndEnabledCondition.class)
|
||||
@ConditionalOnBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
|
||||
static class DiscoveryClientOptionalArgsTlsConfiguration {
|
||||
|
||||
@@ -120,7 +124,7 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnClass(name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientConfiguration {
|
||||
@@ -151,8 +155,8 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass({ "org.glassfish.jersey.client.JerseyClient",
|
||||
"org.springframework.web.reactive.function.client.WebClient" })
|
||||
@Conditional(JerseyClientNotPresentOrNotEnabledCondition.class)
|
||||
@ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled", havingValue = "true")
|
||||
protected static class WebClientNotFoundConfiguration {
|
||||
|
||||
@@ -164,4 +168,40 @@ public class DiscoveryClientOptionalArgsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class JerseyClientPresentAndEnabledCondition extends AllNestedConditions {
|
||||
|
||||
JerseyClientPresentAndEnabledCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
|
||||
static class OnJerseyClientPresent {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "eureka.client.jersey.enabled", matchIfMissing = true)
|
||||
static class OnJerseyClientEnabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class JerseyClientNotPresentOrNotEnabledCondition extends AnyNestedCondition {
|
||||
|
||||
JerseyClientNotPresentOrNotEnabledCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("org.glassfish.jersey.client.JerseyClient")
|
||||
static class OnJerseyClientMissing {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(value = "eureka.client.jersey.enabled", havingValue = "false")
|
||||
static class OnJerseyClientDisabled {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -264,10 +264,10 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
@Override
|
||||
protected boolean hasError(HttpStatusCode statusCode) {
|
||||
/**
|
||||
* When the Eureka server restarts and a client tries to sent a heartbeat the
|
||||
* server will respond with a 404. By default RestTemplate will throw an
|
||||
* When the Eureka server restarts and a client tries to send a heartbeat the
|
||||
* server will respond with a 404. By default, RestTemplate will throw an
|
||||
* exception in this case. What we want is to return the 404 to the upstream
|
||||
* code so it will send another registration request to the server.
|
||||
* code, so it will send another registration request to the server.
|
||||
*/
|
||||
if (statusCode.is4xxClientError()) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2023 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.
|
||||
@@ -59,7 +59,7 @@ import static org.mockserver.model.HttpResponse.response;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Testcontainers
|
||||
public class EurekaConfigServerBootstrapperIT {
|
||||
public class EurekaConfigServerBootstrapperIntegrationTests {
|
||||
|
||||
public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse("mockserver/mockserver")
|
||||
.withTag("mockserver-" + MockServerClient.class.getPackage().getImplementationVersion());
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -37,7 +37,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*", "spring-webflux-*" })
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationNoWebfluxTest {
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationNoWebFluxTests {
|
||||
|
||||
@Test
|
||||
public void contextFailsWithoutWebClient() {
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -36,7 +36,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*" })
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationTest {
|
||||
public class EurekaHttpClientsOptionalArgsConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoadsWithRestTemplate() {
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2017-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.config;
|
||||
|
||||
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for Jersey client setup in DiscoveryClientOptionalArgsConfiguration.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class JerseyClientOptionalArgsConfigurationTests {
|
||||
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent")
|
||||
@Test
|
||||
void shouldCreateRestTemplateDiscoveryClientOptionalArgsWhenJerseyClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DiscoveryClientOptionalArgsConfiguration.class))
|
||||
.withPropertyValues("eureka.client.jersey.enabled=false").run(context -> {
|
||||
assertThat(context).hasSingleBean(AbstractDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context.getBeansOfType(AbstractDiscoveryClientOptionalArgs.class).values().stream()
|
||||
.findFirst().get()).isInstanceOf(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
assertThat(context).hasSingleBean(RestTemplateDiscoveryClientOptionalArgs.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
@DirtiesContext
|
||||
@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
class JerseyOptionalArgsConfigurationTest {
|
||||
class JerseyOptionalArgsConfigurationApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private AbstractDiscoveryClientOptionalArgs optionalArgs;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2022 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test;
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
class RestTemplateTransportClientFactoryTest {
|
||||
class RestTemplateTransportClientFactoryTests {
|
||||
|
||||
private RestTemplateTransportClientFactory transportClientFatory;
|
||||
|
||||
Reference in New Issue
Block a user