Skip to content

Commit 930b927

Browse files
bijukunjummenspencergibb
authored andcommitted
Support for config driven Discovery Client
Making SimpleDiscoveryClient the default, marking NoOpDiscoveryClient as deprecated fixes spring-projectsgh-180
1 parent b40ceef commit 930b927

11 files changed

+341
-19
lines changed

spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClient.java

+5
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,13 @@
2424

2525
/**
2626
* DiscoveryClient used when no implementations are found on the classpath
27+
*
28+
* @deprecated Use {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient instead}
29+
*
2730
* @author Dave Syer
2831
*/
32+
33+
@Deprecated
2934
public class NoopDiscoveryClient implements DiscoveryClient {
3035

3136
private final ServiceInstance instance;

spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java

+5
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,17 @@
4141
import lombok.extern.apachecommons.CommonsLog;
4242

4343
/**
44+
*
45+
* @deprecated Use
46+
* {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration instead}
47+
*
4448
* @author Dave Syer
4549
*/
4650
@Configuration
4751
@EnableConfigurationProperties
4852
@ConditionalOnMissingBean(DiscoveryClient.class)
4953
@CommonsLog
54+
@Deprecated
5055
public class NoopDiscoveryClientAutoConfiguration
5156
implements ApplicationListener<ContextRefreshedEvent> {
5257

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import org.springframework.cloud.client.ServiceInstance;
4+
import org.springframework.cloud.client.discovery.DiscoveryClient;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
/**
10+
* A {@link org.springframework.cloud.client.discovery.DiscoveryClient} that will use the
11+
* properties file as a source of service instances
12+
*
13+
* @author Biju Kunjummen
14+
*/
15+
public class SimpleDiscoveryClient implements DiscoveryClient {
16+
17+
private SimpleDiscoveryProperties simpleDiscoveryProperties;
18+
19+
public SimpleDiscoveryClient(SimpleDiscoveryProperties simpleDiscoveryProperties) {
20+
this.simpleDiscoveryProperties = simpleDiscoveryProperties;
21+
}
22+
23+
@Override
24+
public String description() {
25+
return "Simple Discovery Client";
26+
}
27+
28+
@Override
29+
public ServiceInstance getLocalServiceInstance() {
30+
return null;
31+
}
32+
33+
@Override
34+
public List<ServiceInstance> getInstances(String serviceId) {
35+
List<ServiceInstance> serviceInstances = new ArrayList<>();
36+
List<SimpleServiceInstance> serviceInstanceForService = this.simpleDiscoveryProperties
37+
.getInstances().get(serviceId);
38+
39+
if (serviceInstanceForService != null) {
40+
serviceInstances.addAll(serviceInstanceForService);
41+
}
42+
return serviceInstances;
43+
}
44+
45+
@Override
46+
public List<String> getServices() {
47+
return new ArrayList<>(this.simpleDiscoveryProperties.getInstances().keySet());
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
7+
import org.springframework.cloud.client.discovery.DiscoveryClient;
8+
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.Configuration;
11+
12+
/**
13+
* Spring Boot Auto-Configuration for Simple Properties based Discovery Client
14+
*
15+
* @author Biju Kunjummen
16+
*/
17+
18+
@Configuration
19+
@ConditionalOnMissingBean(DiscoveryClient.class)
20+
@EnableConfigurationProperties(SimpleDiscoveryProperties.class)
21+
@AutoConfigureBefore(NoopDiscoveryClientAutoConfiguration.class)
22+
public class SimpleDiscoveryClientAutoConfiguration {
23+
24+
@Autowired
25+
private SimpleDiscoveryProperties simpleDiscoveryProperties;
26+
27+
@Bean
28+
public DiscoveryClient simpleDiscoveryClient() {
29+
return new SimpleDiscoveryClient(simpleDiscoveryProperties);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import org.springframework.boot.context.properties.ConfigurationProperties;
4+
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
/**
10+
* Properties to hold the details of a
11+
* {@link org.springframework.cloud.client.discovery.DiscoveryClient} service instances
12+
* for a given service
13+
*
14+
* @author Biju Kunjummen
15+
*/
16+
17+
@ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple")
18+
public class SimpleDiscoveryProperties {
19+
private Map<String, List<SimpleServiceInstance>> instances = new HashMap<>();
20+
21+
public Map<String, List<SimpleServiceInstance>> getInstances() {
22+
return instances;
23+
}
24+
25+
public void setInstances(Map<String, List<SimpleServiceInstance>> instances) {
26+
this.instances = instances;
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import java.net.URI;
4+
import java.util.Map;
5+
6+
import org.springframework.cloud.client.ServiceInstance;
7+
8+
/**
9+
* Represents a Simple property based {@link ServiceInstance}
10+
*
11+
* @author Biju Kunjummen
12+
*/
13+
public class SimpleServiceInstance implements ServiceInstance {
14+
15+
private URI resolvedUri;
16+
private String host;
17+
private int port;
18+
private boolean secure;
19+
20+
public SimpleServiceInstance() {
21+
}
22+
23+
public SimpleServiceInstance(String uri) {
24+
setUri(uri);
25+
}
26+
27+
public void setUri(String uri) {
28+
this.resolvedUri = URI.create(uri);
29+
this.host = this.resolvedUri.getHost();
30+
this.port = this.resolvedUri.getPort();
31+
String scheme = this.resolvedUri.getScheme();
32+
if ("https".equals(scheme)) {
33+
this.secure = true;
34+
}
35+
}
36+
37+
@Override
38+
public String getServiceId() {
39+
return null;
40+
}
41+
42+
@Override
43+
public String getHost() {
44+
return this.host;
45+
}
46+
47+
@Override
48+
public int getPort() {
49+
return this.port;
50+
}
51+
52+
@Override
53+
public boolean isSecure() {
54+
return this.secure;
55+
}
56+
57+
@Override
58+
public URI getUri() {
59+
return this.resolvedUri;
60+
}
61+
62+
@Override
63+
public Map<String, String> getMetadata() {
64+
return null;
65+
}
66+
}

spring-cloud-commons/src/main/resources/META-INF/spring.factories

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
66
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
77
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
88
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
9-
org.springframework.cloud.commons.util.UtilAutoConfiguration
9+
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
10+
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
1011

1112

1213
# Environment Post Processors
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.springframework.cloud.client.discovery.noop;
1+
package org.springframework.cloud.client.discovery.simple;
22

33
import org.junit.Test;
44
import org.junit.runner.RunWith;
@@ -10,22 +10,22 @@
1010
import org.springframework.context.annotation.Configuration;
1111
import org.springframework.test.context.junit4.SpringRunner;
1212

13-
import static org.junit.Assert.assertTrue;
13+
import static org.assertj.core.api.Assertions.assertThat;
1414

1515
/**
16-
* Tests if @EnableDiscoveryClient is NOT used, then NoopDiscoveryClient is created.
17-
* @author Spencer Gibb
16+
* DiscoveryClient implementation defaults to {@link SimpleDiscoveryClient}
17+
* @author Biju Kunjummen
1818
*/
1919
@RunWith(SpringRunner.class)
20-
@SpringBootTest(classes = NoopDiscoveryClientConfigurationTests.App.class)
21-
public class NoopDiscoveryClientConfigurationTests {
20+
@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.App.class)
21+
public class DiscoveryClientAutoConfigurationDefaultTests {
2222

2323
@Autowired
2424
DiscoveryClient discoveryClient;
2525

2626
@Test
27-
public void testDiscoveryClientIsNoop() {
28-
assertTrue("discoveryClient is wrong instance type", discoveryClient instanceof NoopDiscoveryClient);
27+
public void simpleDiscoveryClientShouldBeTheDefault() {
28+
assertThat(discoveryClient).isInstanceOf(SimpleDiscoveryClient.class);
2929
}
3030

3131
@EnableAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import org.junit.Test;
4+
import org.junit.runner.RunWith;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
7+
import org.springframework.boot.test.context.SpringBootTest;
8+
import org.springframework.cloud.client.ServiceInstance;
9+
import org.springframework.cloud.client.discovery.DiscoveryClient;
10+
import org.springframework.context.annotation.Configuration;
11+
import org.springframework.test.context.junit4.SpringRunner;
12+
13+
import java.net.URI;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
17+
/**
18+
* Tests for mapping properties to instances in {@link SimpleDiscoveryClient}
19+
*
20+
* @author Biju Kunjummen
21+
*/
22+
23+
@RunWith(SpringRunner.class)
24+
@SpringBootTest(properties = {
25+
"spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s1-1:8080",
26+
"spring.cloud.discovery.client.simple.instances.service1[1].uri=https://s1-2:8443",
27+
"spring.cloud.discovery.client.simple.instances.service2[0].uri=https://s2-1:8080",
28+
"spring.cloud.discovery.client.simple.instances.service2[1].uri=https://s2-2:443" })
29+
public class SimpleDiscoveryClientPropertiesMappingTests {
30+
31+
@Autowired
32+
private SimpleDiscoveryProperties props;
33+
34+
@Autowired
35+
private DiscoveryClient discoveryClient;
36+
37+
@Test
38+
public void propsShouldGetCleanlyMapped() {
39+
assertThat(props.getInstances().size()).isEqualTo(2);
40+
assertThat(props.getInstances().get("service1").size()).isEqualTo(2);
41+
assertThat(props.getInstances().get("service1").get(0).getHost())
42+
.isEqualTo("s1-1");
43+
assertThat(props.getInstances().get("service1").get(0).getPort()).isEqualTo(8080);
44+
assertThat(props.getInstances().get("service1").get(0).getUri())
45+
.isEqualTo(URI.create("http://s1-1:8080"));
46+
assertThat(props.getInstances().get("service1").get(0).isSecure())
47+
.isEqualTo(false);
48+
49+
assertThat(props.getInstances().get("service2").size()).isEqualTo(2);
50+
assertThat(props.getInstances().get("service2").get(0).getHost())
51+
.isEqualTo("s2-1");
52+
assertThat(props.getInstances().get("service2").get(0).getPort()).isEqualTo(8080);
53+
assertThat(props.getInstances().get("service2").get(0).getUri())
54+
.isEqualTo(URI.create("https://s2-1:8080"));
55+
assertThat(props.getInstances().get("service2").get(0).isSecure())
56+
.isEqualTo(true);
57+
}
58+
59+
@Test
60+
public void testDiscoveryClientShouldResolveSimpleValues() {
61+
assertThat(this.discoveryClient.description())
62+
.isEqualTo("Simple Discovery Client");
63+
assertThat(this.discoveryClient.getInstances("service1")).hasSize(2);
64+
65+
ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0);
66+
assertThat(s1.getHost()).isEqualTo("s1-1");
67+
assertThat(s1.getPort()).isEqualTo(8080);
68+
assertThat(s1.getUri()).isEqualTo(URI.create("http://s1-1:8080"));
69+
assertThat(s1.isSecure()).isEqualTo(false);
70+
}
71+
72+
@Test
73+
public void testGetServices() {
74+
assertThat(this.discoveryClient.getServices())
75+
.containsExactlyInAnyOrder("service1", "service2");
76+
}
77+
78+
@Test
79+
public void testGetANonExistentServiceShouldReturnAnEmptyList() {
80+
assertThat(this.discoveryClient.getInstances("nonexistent")).isNotNull();
81+
assertThat(this.discoveryClient.getInstances("nonexistent")).isEmpty();
82+
}
83+
84+
@Configuration
85+
@EnableAutoConfiguration
86+
public static class SampleConfig {
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.springframework.cloud.client.discovery.simple;
2+
3+
import org.junit.Before;
4+
import org.junit.Test;
5+
import org.springframework.cloud.client.ServiceInstance;
6+
7+
import java.net.URI;
8+
import java.util.Arrays;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
/**
16+
* @author Biju Kunjummen
17+
*/
18+
public class SimpleDiscoveryClientTests {
19+
20+
private SimpleDiscoveryClient simpleDiscoveryClient;
21+
22+
@Before
23+
public void setUp() {
24+
SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties();
25+
26+
Map<String, List<SimpleServiceInstance>> map = new HashMap<>();
27+
SimpleServiceInstance service1Inst1 = new SimpleServiceInstance(
28+
"http://host1:8080");
29+
SimpleServiceInstance service1Inst2 = new SimpleServiceInstance(
30+
"https://host2:8443");
31+
map.put("service1", Arrays.asList(service1Inst1, service1Inst2));
32+
simpleDiscoveryProperties.setInstances(map);
33+
this.simpleDiscoveryClient = new SimpleDiscoveryClient(simpleDiscoveryProperties);
34+
}
35+
36+
@Test
37+
public void shouldBeAbleToRetrieveServiceDetailsByName() {
38+
List<ServiceInstance> instances = this.simpleDiscoveryClient
39+
.getInstances("service1");
40+
assertThat(instances.size()).isEqualTo(2);
41+
assertThat(instances.get(0).getHost()).isEqualTo("host1");
42+
assertThat(instances.get(0).getPort()).isEqualTo(8080);
43+
assertThat(instances.get(0).getUri()).isEqualTo(URI.create("http://host1:8080"));
44+
assertThat(instances.get(0).isSecure()).isEqualTo(false);
45+
}
46+
}

0 commit comments

Comments
 (0)