Merge remote-tracking branch 'Upstream/master' into http-client-factories

# Conflicts:
#	spring-cloud-commons/src/main/resources/META-INF/spring.factories
This commit is contained in:
Ryan Baxter
2017-07-06 16:55:44 -04:00
27 changed files with 652 additions and 198 deletions

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<name>Spring Cloud Commons Docs</name>

View File

@@ -317,6 +317,10 @@ Commons provides the `@EnableDiscoveryClient` annotation. This looks for impleme
By default, implementations of `DiscoveryClient` will auto-register the local Spring Boot server with the remote discovery server. This can be disabled by setting `autoRegister=false` in `@EnableDiscoveryClient`.
==== Health Indicator
Commons creates a Spring Boot `HealthIndicator` that `DiscoveryClient` implementations can participate in by implementing `DiscoveryHealthIndicator`. To disable the composite `HealthIndicator` set `spring.cloud.discovery.client.composite-indicator.enabled=false`. A generic `HealthIndicator` based on `DiscoveryClient` is auto-configured (`DiscoveryClientHealthIndicator). To disable it, set `spring.cloud.discovery.client.health-indicator.enabled=false`. To disable the description field of the `DiscoveryClientHealthIndicator` set `spring.cloud.discovery.client.health-indicator.include-description=false`, otherwise it can bubble up as the `description` of the rolled up `HealthIndicator`.
=== ServiceRegistry
Commons now provides a `ServiceRegistry` interface which provides methods like `register(Registration)` and `deregister(Registration)` which allow you to provide custom registered services. `Registration` is a marker interface.

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Commons Parent</name>
<description>Spring Cloud Commons Parent</description>

View File

@@ -9,7 +9,7 @@
<relativePath/>
</parent>
<artifactId>spring-cloud-commons-dependencies</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-commons-dependencies</name>
<description>Spring Cloud Commons Dependencies</description>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-commons</artifactId>

View File

@@ -28,10 +28,12 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.actuator.FeaturesEndpoint;
import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator;
import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties;
import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator;
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
@@ -48,6 +50,7 @@ import org.springframework.context.annotation.Configuration;
public class CommonsClientAutoConfiguration {
@Configuration
@EnableConfigurationProperties(DiscoveryClientHealthIndicatorProperties.class)
@ConditionalOnClass(HealthIndicator.class)
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnProperty(value = "spring.cloud.discovery.enabled", matchIfMissing = true)
@@ -55,8 +58,8 @@ public class CommonsClientAutoConfiguration {
@Bean
@ConditionalOnProperty(value = "spring.cloud.discovery.client.health-indicator.enabled", matchIfMissing = true)
public DiscoveryClientHealthIndicator discoveryClientHealthIndicator(
DiscoveryClient discoveryClient) {
return new DiscoveryClientHealthIndicator(discoveryClient);
DiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
return new DiscoveryClientHealthIndicator(discoveryClient, properties);
}
@Bean

View File

@@ -0,0 +1,73 @@
package org.springframework.cloud.client.discovery.composite;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
/**
* A {@link DiscoveryClient} composed of other Discovery Client's and will delegate the
* calls to each of them in order
*
* @author Biju Kunjummen
*/
public class CompositeDiscoveryClient implements DiscoveryClient {
private final List<DiscoveryClient> discoveryClients;
public CompositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
this.discoveryClients = discoveryClients;
}
@Override
public String description() {
return "Composite Discovery Client";
}
@Override
public ServiceInstance getLocalServiceInstance() {
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : discoveryClients) {
ServiceInstance serviceInstance = discoveryClient.getLocalServiceInstance();
if (serviceInstance != null) {
return serviceInstance;
}
}
}
return null;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : discoveryClients) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
if (instances != null && instances.size() > 0) {
return instances;
}
}
}
return Collections.emptyList();
}
@Override
public List<String> getServices() {
LinkedHashSet<String> services = new LinkedHashSet<>();
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : discoveryClients) {
List<String> serviceForClient = discoveryClient.getServices();
if (serviceForClient != null) {
services.addAll(serviceForClient);
}
}
}
return new ArrayList<>(services);
}
public List<DiscoveryClient> getDiscoveryClients() {
return discoveryClients;
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.cloud.client.discovery.composite;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.List;
/**
* Auto-configuration for Composite Discovery Client.
*
* @author Biju Kunjummen
*/
@Configuration
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class CompositeDiscoveryClientAutoConfiguration {
@Bean
@Primary
public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
return new CompositeDiscoveryClient(discoveryClients);
}
}

View File

@@ -39,10 +39,17 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator,
private int order = Ordered.HIGHEST_PRECEDENCE;
private DiscoveryClient discoveryClient;
private final DiscoveryClient discoveryClient;
private final DiscoveryClientHealthIndicatorProperties properties;
@Deprecated
public DiscoveryClientHealthIndicator(DiscoveryClient discoveryClient) {
this(discoveryClient, new DiscoveryClientHealthIndicatorProperties());
}
public DiscoveryClientHealthIndicator(DiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) {
this.discoveryClient = discoveryClient;
this.properties = properties;
}
@Override
@@ -59,7 +66,8 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator,
if (this.discoveryInitialized.get()) {
try {
List<String> services = this.discoveryClient.getServices();
builder.status(new Status("UP", this.discoveryClient.description()))
String description = (this.properties.isIncludeDescription()) ? this.discoveryClient.description() : "";
builder.status(new Status("UP", description))
.withDetail("services", services);
}
catch (Exception e) {

View File

@@ -0,0 +1,40 @@
package org.springframework.cloud.client.discovery.health;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Spencer Gibb
*/
@ConfigurationProperties("spring.cloud.discovery.client.health-indicator")
public class DiscoveryClientHealthIndicatorProperties {
private boolean enabled = true;
//TODO: change to false in 2.0.0
private boolean includeDescription = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isIncludeDescription() {
return includeDescription;
}
public void setIncludeDescription(boolean includeDescription) {
this.includeDescription = includeDescription;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("DiscoveryClientHealthIndicatorProperties{");
sb.append("enabled=").append(enabled);
sb.append(", includeDescription=").append(includeDescription);
sb.append('}');
return sb.toString();
}
}

View File

@@ -1,23 +1,23 @@
package org.springframework.cloud.client.discovery.simple;
import java.net.URI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.ClassUtils;
import java.net.URI;
/**
* Spring Boot Auto-Configuration for Simple Properties based Discovery Client
*
@@ -25,8 +25,6 @@ import org.springframework.util.ClassUtils;
*/
@Configuration
@ConditionalOnMissingBean(DiscoveryClient.class)
@EnableConfigurationProperties
@AutoConfigureBefore(NoopDiscoveryClientAutoConfiguration.class)
public class SimpleDiscoveryClientAutoConfiguration {
@@ -54,9 +52,9 @@ public class SimpleDiscoveryClientAutoConfiguration {
}
@Bean
public DiscoveryClient simpleDiscoveryClient(
SimpleDiscoveryProperties simpleDiscoveryProperties) {
return new SimpleDiscoveryClient(simpleDiscoveryProperties);
@Order(Ordered.LOWEST_PRECEDENCE)
public DiscoveryClient simpleDiscoveryClient() {
return new SimpleDiscoveryClient(simpleDiscoveryProperties());
}
private int findPort() {

View File

@@ -7,6 +7,7 @@ org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration,\
org.springframework.cloud.commons.httpclient.HttpClientConfiguration

View File

@@ -0,0 +1,79 @@
package org.springframework.cloud.client.discovery.composite;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Composite Discovery Client should be the one found by default.
*
* @author Biju Kunjummen
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class CompositeDiscoveryClientAutoConfigurationTests {
@Autowired
private DiscoveryClient discoveryClient;
@Test
public void compositeDiscoveryClientShouldBeTheDefault() {
assertThat(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) discoveryClient;
assertThat(compositeDiscoveryClient.getDiscoveryClients()).hasSize(2);
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(0).description())
.isEqualTo("A custom discovery client");
}
@Test
public void simpleDiscoveryClientShouldBeHaveTheLowestPrecedence() {
CompositeDiscoveryClient compositeDiscoveryClient = (CompositeDiscoveryClient) discoveryClient;
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(0).description())
.isEqualTo("A custom discovery client");
assertThat(compositeDiscoveryClient.getDiscoveryClients().get(1))
.isInstanceOf(SimpleDiscoveryClient.class);
}
@EnableAutoConfiguration
@Configuration
public static class Config {
@Bean
public DiscoveryClient customDiscoveryClient1() {
return new DiscoveryClient() {
@Override
public String description() {
return "A custom discovery client";
}
@Override
public ServiceInstance getLocalServiceInstance() {
return null;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
return null;
}
@Override
public List<String> getServices() {
return null;
}
};
}
}
}

View File

@@ -0,0 +1,116 @@
package org.springframework.cloud.client.discovery.composite;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.junit4.SpringRunner;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for behavior of Composite Discovery Client
*
* @author Biju Kunjummen
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {
"spring.application.name=service0",
"spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s1-1:8080",
"spring.cloud.discovery.client.simple.instances.service1[1].uri=https://s1-2:8443",
"spring.cloud.discovery.client.simple.instances.service2[0].uri=https://s2-1:8080",
"spring.cloud.discovery.client.simple.instances.service2[1].uri=https://s2-2:443" })
public class CompositeDiscoveryClientTests {
@Autowired
private DiscoveryClient discoveryClient;
@Test
public void getInstancesByServiceIdShouldDelegateCall() {
assertThat(this.discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
assertThat(this.discoveryClient.getInstances("service1")).hasSize(2);
ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0);
assertThat(s1.getHost()).isEqualTo("s1-1");
assertThat(s1.getPort()).isEqualTo(8080);
assertThat(s1.getUri()).isEqualTo(URI.create("http://s1-1:8080"));
assertThat(s1.isSecure()).isEqualTo(false);
}
@Test
public void getServicesShouldAggregateAllServiceNames() {
assertThat(this.discoveryClient.getServices()).containsOnlyOnce("service1", "service2", "custom");
}
@Test
public void getDescriptionShouldBeComposite() {
assertThat(this.discoveryClient.description()).isEqualTo("Composite Discovery Client");
}
@Test
public void getInstancesShouldRespectOrder() {
assertThat(this.discoveryClient.getInstances("custom")).hasSize(1);
assertThat(this.discoveryClient.getInstances("custom")).hasSize(1);
}
@Test
public void getInstancesByUnknownServiceIdShouldReturnAnEmptyList() {
assertThat(this.discoveryClient.getInstances("unknown")).hasSize(0);
}
@Test
public void localServiceInstanceShouldReturnTheFirstMatch() {
assertThat(this.discoveryClient.getLocalServiceInstance().getServiceId()).isEqualTo("service0");
}
@EnableAutoConfiguration
@Configuration
public static class Config {
@Bean
@Order(1)
public DiscoveryClient customDiscoveryClient() {
return new DiscoveryClient() {
@Override
public String description() {
return "A custom discovery client";
}
@Override
public ServiceInstance getLocalServiceInstance() {
return null;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
if (serviceId.equals("custom")) {
ServiceInstance s1 = new DefaultServiceInstance("custom", "host",
123, false);
return Arrays.asList(s1);
}
return Collections.emptyList();
}
@Override
public List<String> getServices() {
return Arrays.asList("custom");
}
};
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2013-2015 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
*
* http://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.client.discovery.health;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { DiscoveryClientHealthIndicatorTests.Config.class,
CommonsClientAutoConfiguration.class }, properties = "spring.cloud.discovery.client.health-indicator.include-description:false")
public class DiscoveryClientHealthIndicatorTests {
@Autowired
private DiscoveryCompositeHealthIndicator healthIndicator;
@Autowired
private DiscoveryClientHealthIndicator clientHealthIndicator;
@Configuration
@EnableConfigurationProperties
public static class Config {
@Bean
public HealthAggregator healthAggregator() {
return new OrderedHealthAggregator();
}
@Bean
public DiscoveryClient discoveryClient() {
DiscoveryClient mock = mock(DiscoveryClient.class);
given(mock.description()).willReturn("TestDiscoveryClient");
given(mock.getServices()).willReturn(Arrays.asList("TestService1"));
return mock;
}
@Bean
public DiscoveryHealthIndicator discoveryHealthIndicator() {
return new DiscoveryHealthIndicator() {
@Override
public String getName() {
return "testDiscoveryHealthIndicator";
}
@Override
public Health health() {
return new Health.Builder().unknown().build();
}
};
}
}
@Test
public void testHealthIndicatorDescriptionDisabled() {
assertNotNull("healthIndicator was null", this.healthIndicator);
Health health = this.healthIndicator.health();
assertHealth(health, Status.UNKNOWN);
clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent<>(this, null));
health = this.healthIndicator.health();
Status status = assertHealth(health, Status.UP);
assertEquals("status description was wrong", "",
status.getDescription());
}
private Status assertHealth(Health health, Status expected) {
assertNotNull("health was null", health);
Status status = health.getStatus();
assertNotNull("status was null", status);
assertEquals("status code was wrong", expected.getCode(), status.getCode());
return status;
}
}

View File

@@ -16,42 +16,41 @@
package org.springframework.cloud.client.discovery.health;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { DiscoveryCompositeHealthIndicatorTests.Config.class,
@SpringBootTest(classes = { DiscoveryCompositeHealthIndicatorTests.Config.class,
CommonsClientAutoConfiguration.class })
public class DiscoveryCompositeHealthIndicatorTests {
@Autowired
DiscoveryCompositeHealthIndicator healthIndicator;
private DiscoveryCompositeHealthIndicator healthIndicator;
@Autowired
DiscoveryClientHealthIndicator clientHealthIndicator;
private DiscoveryClientHealthIndicator clientHealthIndicator;
@Configuration
public static class Config {
@@ -90,11 +89,11 @@ public class DiscoveryCompositeHealthIndicatorTests {
Health health = this.healthIndicator.health();
assertHealth(health, Status.UNKNOWN);
clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent<Object>(this, null));
clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent<>(this, null));
health = this.healthIndicator.health();
Status status = assertHealth(health, Status.UP);
assertEquals("status desciption was wrong", "TestDiscoveryClient",
assertEquals("status description was wrong", "TestDiscoveryClient",
status.getDescription());
}
@@ -105,9 +104,5 @@ public class DiscoveryCompositeHealthIndicatorTests {
assertEquals("status code was wrong", expected.getCode(), status.getCode());
return status;
}
public static void main(String[] args) {
SpringApplication.run(new Object[]{Config.class,CommonsClientAutoConfiguration.class}, new String[] {"--debug", "--spring.main.webEnvironment=false"});
}
}

View File

@@ -3,36 +3,34 @@ package org.springframework.cloud.client.discovery.simple;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* DiscoveryClient implementation defaults to {@link SimpleDiscoveryClient}
* DiscoveryClient implementation defaults to {@link CompositeDiscoveryClient}
*
* @author Biju Kunjummen
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.App.class)
@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.Config.class)
public class DiscoveryClientAutoConfigurationDefaultTests {
@Autowired
DiscoveryClient discoveryClient;
private DiscoveryClient discoveryClient;
@Test
public void simpleDiscoveryClientShouldBeTheDefault() {
assertThat(discoveryClient).isInstanceOf(SimpleDiscoveryClient.class);
assertThat(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
}
@EnableAutoConfiguration
@Configuration
public static class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
public static class Config {
}
}

View File

@@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
@@ -32,7 +31,7 @@ public class SimpleDiscoveryClientPropertiesMappingTests {
private SimpleDiscoveryProperties props;
@Autowired
private DiscoveryClient discoveryClient;
private SimpleDiscoveryClient discoveryClient;
@Test
public void propsShouldGetCleanlyMapped() {

View File

@@ -1,70 +0,0 @@
package org.springframework.cloud.client.discovery.simple;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Biju Kunjummen
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = UserDefinedDiscoveryClientOverridesDefaultsTests.App.class)
public class UserDefinedDiscoveryClientOverridesDefaultsTests {
@Autowired
DiscoveryClient discoveryClient;
@Test
public void testDiscoveryClientIsNotNoop() {
assertThat(discoveryClient).isNotInstanceOf(SimpleDiscoveryClient.class);
assertThat(discoveryClient.description())
.isEqualTo("user defined discovery client");
}
@EnableAutoConfiguration
@Configuration
public static class App {
@Bean
public DiscoveryClient discoveryClient() {
return new DiscoveryClient() {
@Override
public String description() {
return "user defined discovery client";
}
@Override
public ServiceInstance getLocalServiceInstance() {
return null;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
return null;
}
@Override
public List<String> getServices() {
return null;
}
};
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-context</artifactId>

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.cloud.autoconfigure;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -44,17 +44,13 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(EnvironmentEndpoint.class)
@ConditionalOnWebApplication
@ConditionalOnBean(RestartEndpoint.class)
@AutoConfigureAfter({ WebMvcAutoConfiguration.class,
RefreshEndpointAutoConfiguration.class })
public class LifecycleMvcEndpointAutoConfiguration {
@Autowired
private RestartEndpoint restartEndpoint;
@Bean
@ConditionalOnBean(EnvironmentEndpoint.class)
@ConditionalOnProperty(value = "endpoints.env.post.enabled", matchIfMissing = true)
@ConditionalOnEnabledEndpoint(value = "env.post")
public EnvironmentManagerMvcEndpoint environmentManagerEndpoint(
EnvironmentEndpoint delegate, EnvironmentManager environment) {
return new EnvironmentManagerMvcEndpoint(delegate, environment);
@@ -67,8 +63,9 @@ public class LifecycleMvcEndpointAutoConfiguration {
}
@Bean
public RestartMvcEndpoint restartMvcEndpoint() {
return new RestartMvcEndpoint(this.restartEndpoint);
@ConditionalOnBean(RestartEndpoint.class)
public RestartMvcEndpoint restartMvcEndpoint(RestartEndpoint restartEndpoint) {
return new RestartMvcEndpoint(restartEndpoint);
}
@Bean

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.autoconfigure;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -26,7 +27,6 @@ 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.context.properties.ConfigurationProperties;
import org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration;
import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;
import org.springframework.cloud.context.refresh.ContextRefresher;
@@ -57,6 +57,7 @@ public class RefreshEndpointAutoConfiguration {
}
@ConditionalOnClass(IntegrationMBeanExporter.class)
@ConditionalOnEnabledEndpoint(value = "restart", enabledByDefault = false)
protected static class RestartEndpointWithIntegration {
@Autowired(required = false)
@@ -75,30 +76,38 @@ public class RefreshEndpointAutoConfiguration {
}
@ConditionalOnMissingClass("org.springframework.integration.monitor.IntegrationMBeanExporter")
@ConditionalOnEnabledEndpoint(value = "restart", enabledByDefault = false)
protected static class RestartEndpointWithoutIntegration {
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
public RestartEndpoint restartEndpointWithoutIntegration() {
return new RestartEndpoint();
}
}
@Bean
@ConfigurationProperties("endpoints.pause")
public RestartEndpoint.PauseEndpoint pauseEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getPauseEndpoint();
}
@ConditionalOnEnabledEndpoint(value = "restart", enabledByDefault = false)
protected static class PauseResumeEndpoints {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint("pause")
public RestartEndpoint.PauseEndpoint pauseEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getPauseEndpoint();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint("resume")
public RestartEndpoint.ResumeEndpoint resumeEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getResumeEndpoint();
}
@Bean
@ConfigurationProperties("endpoints.resume")
public RestartEndpoint.ResumeEndpoint resumeEndpoint(
RestartEndpoint restartEndpoint) {
return restartEndpoint.getResumeEndpoint();
}
@Configuration
@ConditionalOnProperty(value = "endpoints.refresh.enabled", matchIfMissing = true)
@ConditionalOnEnabledEndpoint("refresh")
@ConditionalOnBean(PropertySourceBootstrapConfiguration.class)
protected static class RefreshEndpointConfiguration {
@@ -110,4 +119,4 @@ public class RefreshEndpointAutoConfiguration {
}
}
}
}

View File

@@ -114,7 +114,7 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean>
return new ResumeEndpoint();
}
@ConfigurationProperties("endpoints")
@ConfigurationProperties("endpoints.pause")
public class PauseEndpoint extends AbstractEndpoint<Boolean> {
public PauseEndpoint() {
@@ -131,7 +131,7 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean>
}
}
@ConfigurationProperties("endpoints")
@ConfigurationProperties("endpoints.resume")
public class ResumeEndpoint extends AbstractEndpoint<Boolean> {
public ResumeEndpoint() {

View File

@@ -1,83 +1,152 @@
package org.springframework.cloud.autoconfigure;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* @author Spencer Gibb
*/
public class LifecycleMvcAutoConfigurationTests {
// postEnvMvcEndpoint
@Test
public void postEnvMvcEndpointDisabled() {
try (ConfigurableApplicationContext context = getApplicationContext(Config.class,
"server.port=0", "endpoints.env.post.enabled=false")) {
assertThat(context
.getBeanNamesForType(EnvironmentManagerMvcEndpoint.class).length,
is(equalTo(0)));
beanNotCreated("environmentManagerEndpoint",
"endpoints.env.post.enabled=false");
}
@Test
public void postEnvMvcEndpointGloballyDisabled() {
beanNotCreated("environmentManagerEndpoint",
"endpoints.enabled=false");
}
@Test
public void postEnvMvcEndpointEnabled() {
beanCreated("environmentManagerEndpoint",
"endpoints.env.post.enabled=true");
}
// restartMvcEndpoint
@Test
public void restartMvcEndpointDisabled() {
beanNotCreated("restartMvcEndpoint",
"endpoints.restart.enabled=false");
}
@Test
public void restartMvcEndpointGloballyDisabled() {
beanNotCreated("restartMvcEndpoint",
"endpoints.enabled=false");
}
@Test
public void restartMvcEndpointEnabled() {
beanCreatedAndEndpointEnabled("restartMvcEndpoint",
"endpoints.restart.enabled=true");
}
// pauseMvcEndpoint
@Test
public void pauseMvcEndpointDisabled() {
beanNotCreated("pauseMvcEndpoint",
"endpoints.pause.enabled=false");
}
@Test
public void pauseMvcEndpointRestartDisabled() {
beanNotCreated("pauseMvcEndpoint",
"endpoints.restart.enabled=false",
"endpoints.pause.enabled=true");
}
@Test
public void pauseMvcEndpointGloballyDisabled() {
beanNotCreated("pauseMvcEndpoint",
"endpoints.enabled=false");
}
@Test
public void pauseMvcEndpointEnabled() {
beanCreatedAndEndpointEnabled("pauseMvcEndpoint",
"endpoints.restart.enabled=true",
"endpoints.pause.enabled=true");
}
// resumeMvcEndpoint
@Test
public void resumeMvcEndpointDisabled() {
beanNotCreated("resumeMvcEndpoint",
"endpoints.restart.enabled=true",
"endpoints.resume.enabled=false");
}
@Test
public void resumeMvcEndpointRestartDisabled() {
beanNotCreated("resumeMvcEndpoint",
"endpoints.restart.enabled=false",
"endpoints.resume.enabled=true");
}
@Test
public void resumeMvcEndpointGloballyDisabled() {
beanNotCreated("resumeMvcEndpoint",
"endpoints.enabled=false");
}
@Test
public void resumeMvcEndpointEnabled() {
beanCreatedAndEndpointEnabled("resumeMvcEndpoint",
"endpoints.restart.enabled=true",
"endpoints.resume.enabled=true");
}
private void beanNotCreated(String beanName, String... contextProperties) {
try (ConfigurableApplicationContext context = getApplicationContext(Config.class, contextProperties)) {
assertThat("bean was created", context.containsBeanDefinition(beanName), equalTo(false));
}
}
@Test
public void pauseMvcEndpointDisabled() {
endpointDisabled("endpoints.pause.enabled", "pauseMvcEndpoint");
private void beanCreated(String beanName, String... contextProperties) {
try (ConfigurableApplicationContext context = getApplicationContext(Config.class, contextProperties)) {
assertThat("bean was not created", context.containsBeanDefinition(beanName), equalTo(true));
}
}
@Test
public void resumeMvcEndpointDisabled() {
endpointDisabled("endpoints.resume.enabled", "resumeMvcEndpoint");
}
private void beanCreatedAndEndpointEnabled(String beanName, String... properties) {
try (ConfigurableApplicationContext context = getApplicationContext(Config.class, properties)) {
assertThat("bean was not created", context.containsBeanDefinition(beanName), equalTo(true));
@Test
public void restartMvcEndpointDisabled() {
endpointDisabled("endpoints.restart.enabled", "restartMvcEndpoint");
}
@Test
public void pauseMvcEndpointGloballyDisabled() {
endpointDisabled("endpoints.enabled", "pauseMvcEndpoint");
}
@Test
public void resumeMvcEndpointGloballyDisabled() {
endpointDisabled("endpoints.enabled", "resumeMvcEndpoint");
}
@Test
public void restartMvcEndpointGloballyDisabled() {
endpointDisabled("endpoints.enabled", "restartMvcEndpoint");
}
private void endpointDisabled(String enabledProp, String beanName) {
try (ConfigurableApplicationContext context = getApplicationContext(Config.class,
"server.port=0", enabledProp + "=false")) {
EndpointMvcAdapter endpoint = context.getBean(beanName,
EndpointMvcAdapter.class);
EndpointMvcAdapter endpoint = context.getBean(beanName, EndpointMvcAdapter.class);
Object result = endpoint.invoke();
assertThat("result is wrong type", result,
is(instanceOf(ResponseEntity.class)));
ResponseEntity<?> response = (ResponseEntity<?>) result;
assertThat("response code was wrong", response.getStatusCode(),
equalTo(HttpStatus.NOT_FOUND));
is(not(instanceOf(ResponseEntity.class))));
}
}
private static ConfigurableApplicationContext getApplicationContext(
Class<?> configuration, String... properties) {
return new SpringApplicationBuilder(configuration).properties(properties).run();
List<String> defaultProperties = Lists.newArrayList(properties);
defaultProperties.add("server.port=0");
defaultProperties.add("spring.jmx.default-domain=${random.uuid}");
return new SpringApplicationBuilder(configuration).properties(defaultProperties.toArray(new String[]{})).run();
}
@Configuration

View File

@@ -24,14 +24,13 @@ public class RefreshAutoConfigurationClassPathTests {
try (ConfigurableApplicationContext context = getApplicationContext(
Config.class)) {
assertFalse(context.getBeansOfType(RefreshEventListener.class).isEmpty());
assertFalse(context.containsBean("refeshEndpoint"));
assertFalse(context.containsBean("refreshEndpoint"));
}
}
private static ConfigurableApplicationContext getApplicationContext(
Class<?> configuration, String... properties) {
return new SpringApplicationBuilder(configuration).web(false)
.properties(properties).run();
return new SpringApplicationBuilder(configuration).web(false).properties(properties).run();
}
@Configuration

View File

@@ -33,8 +33,7 @@ public class RefreshAutoConfigurationTests {
private static ConfigurableApplicationContext getApplicationContext(
Class<?> configuration, String... properties) {
return new SpringApplicationBuilder(configuration).web(false)
.properties(properties).run();
return new SpringApplicationBuilder(configuration).web(false).properties(properties).run();
}
@Configuration

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-parent</artifactId>
<version>1.2.3.BUILD-SNAPSHOT</version>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-starter</artifactId>
<name>spring-cloud-starter</name>