Merge branch '2.2.x'
This commit is contained in:
@@ -41,11 +41,9 @@
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -57,7 +55,6 @@
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
@@ -73,6 +72,8 @@ public class EurekaConfigServerBootstrapConfiguration {
|
||||
@ConditionalOnMissingBean(EurekaHttpClient.class)
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
havingValue = "true")
|
||||
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(
|
||||
EurekaClientConfigBean config) {
|
||||
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory()
|
||||
@@ -81,7 +82,8 @@ public class EurekaConfigServerBootstrapConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(EurekaHttpClient.class)
|
||||
@ConditionalOnMissingClass("org.springframework.web.reactive.function.client.WebClient")
|
||||
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
|
||||
matchIfMissing = true, havingValue = "false")
|
||||
public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(
|
||||
EurekaClientConfigBean config) {
|
||||
return (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory()
|
||||
|
||||
@@ -89,8 +89,7 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
}
|
||||
|
||||
private void setExchangeStrategies(WebClient.Builder builder) {
|
||||
ObjectMapper objectMapper = mappingJacksonHttpMessageConverter()
|
||||
.getObjectMapper();
|
||||
ObjectMapper objectMapper = objectMapper();
|
||||
ExchangeStrategies strategies = ExchangeStrategies.builder()
|
||||
.codecs(clientDefaultCodecsConfigurer -> {
|
||||
clientDefaultCodecsConfigurer.defaultCodecs()
|
||||
@@ -105,11 +104,11 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
}
|
||||
|
||||
private void skipHttp400Error(WebClient.Builder builder) {
|
||||
builder.filter(Http4xxErrorExchangeFilterFunction());
|
||||
builder.filter(http4XxErrorExchangeFilterFunction());
|
||||
}
|
||||
|
||||
// Skip over 4xx http errors
|
||||
private ExchangeFilterFunction Http4xxErrorExchangeFilterFunction() {
|
||||
private ExchangeFilterFunction http4XxErrorExchangeFilterFunction() {
|
||||
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||
// literally 400 pass the tests, not 4xxClientError
|
||||
if (clientResponse.statusCode().value() == 400) {
|
||||
@@ -132,54 +131,48 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @deprecated to be removed.
|
||||
* @return a {@link MappingJackson2HttpMessageConverter} object
|
||||
*/
|
||||
@Deprecated
|
||||
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
converter.setObjectMapper(new ObjectMapper()
|
||||
.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE));
|
||||
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier()); // keyFormatter,
|
||||
// compact));
|
||||
converter.getObjectMapper().registerModule(jsonModule);
|
||||
|
||||
converter.getObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true);
|
||||
converter.getObjectMapper().configure(DeserializationFeature.UNWRAP_ROOT_VALUE,
|
||||
true);
|
||||
converter.getObjectMapper().addMixIn(Applications.class,
|
||||
ApplicationsJsonMixIn.class);
|
||||
converter.getObjectMapper().addMixIn(InstanceInfo.class,
|
||||
InstanceInfoJsonMixIn.class);
|
||||
|
||||
// converter.getObjectMapper().addMixIn(DataCenterInfo.class,
|
||||
// DataCenterInfoXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(InstanceInfo.PortWrapper.class,
|
||||
// PortWrapperXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(Application.class,
|
||||
// ApplicationXmlMixIn.class);
|
||||
// converter.getObjectMapper().addMixIn(Applications.class,
|
||||
// ApplicationsXmlMixIn.class);
|
||||
|
||||
converter.setObjectMapper(objectMapper());
|
||||
return converter;
|
||||
}
|
||||
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() { // final
|
||||
// KeyFormatter
|
||||
// keyFormatter,
|
||||
// final
|
||||
// boolean
|
||||
// compactMode)
|
||||
// {
|
||||
/**
|
||||
* Provides the serialization configurations required by the Eureka Server. JSON
|
||||
* content exchanged with eureka requires a root node matching the entity being
|
||||
* serialized or deserialized. Achieved with
|
||||
* {@link SerializationFeature#WRAP_ROOT_VALUE} and
|
||||
* {@link DeserializationFeature#UNWRAP_ROOT_VALUE}.
|
||||
* {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
|
||||
* {@link ObjectMapper}.
|
||||
* @return a {@link ObjectMapper} object
|
||||
*/
|
||||
private ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
|
||||
|
||||
SimpleModule jsonModule = new SimpleModule();
|
||||
jsonModule.setSerializerModifier(createJsonSerializerModifier());
|
||||
objectMapper.registerModule(jsonModule);
|
||||
|
||||
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
|
||||
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
|
||||
objectMapper.addMixIn(Applications.class, ApplicationsJsonMixIn.class);
|
||||
objectMapper.addMixIn(InstanceInfo.class, InstanceInfoJsonMixIn.class);
|
||||
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
@Deprecated // reduce visibility in future release
|
||||
public static BeanSerializerModifier createJsonSerializerModifier() {
|
||||
return new BeanSerializerModifier() {
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config,
|
||||
BeanDescription beanDesc, JsonSerializer<?> serializer) {
|
||||
/*
|
||||
* if (beanDesc.getBeanClass().isAssignableFrom(Applications.class)) {
|
||||
* return new ApplicationsJsonBeanSerializer((BeanSerializerBase)
|
||||
* serializer, keyFormatter); }
|
||||
*/
|
||||
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
|
||||
return new InstanceInfoJsonBeanSerializer(
|
||||
(BeanSerializerBase) serializer, false);
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.netflix.eureka.loadbalancer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfigurationRegistrar;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
@@ -34,9 +35,10 @@ import org.springframework.core.env.Environment;
|
||||
* @see EurekaLoadBalancerClientConfiguration
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(EurekaLoadBalancerProperties.class)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnClass(LoadBalancerClientConfigurationRegistrar.class)
|
||||
@LoadBalancerClients(defaultConfiguration = EurekaLoadBalancerClientConfiguration.class)
|
||||
@ConditionalOnProperty(name = "eureka.client.enabled", matchIfMissing = true)
|
||||
public class LoadBalancerEurekaAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
||||
@@ -123,7 +123,7 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
|
||||
String refinedContextPath = '/'
|
||||
+ StringUtils.trimLeadingCharacter(contextPath, '/');
|
||||
URL base = new URL(scheme, hostname, port, refinedContextPath);
|
||||
String refinedStatusPath = StringUtils.trimLeadingCharacter(statusPath, '/');
|
||||
String refinedStatusPath = refinedStatusPath(statusPath, contextPath);
|
||||
return new URL(base, refinedStatusPath).toString();
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
@@ -133,6 +133,13 @@ public class DefaultManagementMetadataProvider implements ManagementMetadataProv
|
||||
}
|
||||
}
|
||||
|
||||
private String refinedStatusPath(String statusPath, String contextPath) {
|
||||
if (statusPath.startsWith(contextPath) && !"/".equals(contextPath)) {
|
||||
statusPath = StringUtils.replace(statusPath, contextPath, "");
|
||||
}
|
||||
return StringUtils.trimLeadingCharacter(statusPath, '/');
|
||||
}
|
||||
|
||||
private String getErrorMessage(String scheme, String hostname, int port,
|
||||
String contextPath, String statusPath) {
|
||||
return String.format(
|
||||
|
||||
@@ -325,6 +325,20 @@ public class EurekaClientAutoConfigurationTests {
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthCheckUrlPathWithServerPortAndContextPathKebobCase() {
|
||||
TestPropertyValues.of("server.port=8989",
|
||||
"server.servlet.context-path=/servletContextPath",
|
||||
"eureka.instance.health-check-url-path=${server.servlet.context-path:}/myHealthCheck")
|
||||
.applyTo(this.context);
|
||||
setupContext(RefreshAutoConfiguration.class);
|
||||
EurekaInstanceConfigBean instance = this.context
|
||||
.getBean(EurekaInstanceConfigBean.class);
|
||||
assertThat(instance.getHealthCheckUrl())
|
||||
.as("Wrong health check: " + instance.getHealthCheckUrl())
|
||||
.endsWith(":8989/servletContextPath/myHealthCheck");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusPageUrlPathAndManagementPortKabobCase() {
|
||||
TestPropertyValues
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
|
||||
import org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient;
|
||||
import org.springframework.cloud.netflix.eureka.http.WebClientEurekaHttpClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -36,7 +37,8 @@ public class EurekaConfigServerBootstrapConfigurationWebClientTests {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true")
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true",
|
||||
"eureka.client.webclient.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).hasSingleBean(WebClientEurekaHttpClient.class);
|
||||
@@ -45,4 +47,19 @@ public class EurekaConfigServerBootstrapConfigurationWebClientTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void properBeansCreatedWhenEnabledWebClientDisabled() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(EurekaConfigServerBootstrapConfiguration.class))
|
||||
.withPropertyValues("spring.cloud.config.discovery.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EurekaClientConfigBean.class);
|
||||
assertThat(context).doesNotHaveBean(WebClientEurekaHttpClient.class);
|
||||
assertThat(context).hasSingleBean(RestTemplateEurekaHttpClient.class);
|
||||
assertThat(context)
|
||||
.hasSingleBean(ConfigServerInstanceProvider.Function.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.cloud.netflix.eureka.loadbalancer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.cloud.commons.util.InetUtilsProperties;
|
||||
import org.springframework.cloud.loadbalancer.config.LoadBalancerZoneConfig;
|
||||
@@ -72,4 +74,16 @@ class EurekaLoadBalancerClientConfigurationTests {
|
||||
assertThat(zoneConfig.getZone()).isEqualTo("is.a.test.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabledViaProperty() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(LoadBalancerEurekaAutoConfiguration.class))
|
||||
.withPropertyValues("eureka.client.enabled=false").run(context -> {
|
||||
assertThat(context)
|
||||
.doesNotHaveBean(EurekaLoadBalancerProperties.class);
|
||||
assertThat(context).doesNotHaveBean(LoadBalancerZoneConfig.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user