diff --git a/pom.xml b/pom.xml
index fa7666be..73518c2c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,17 +39,41 @@
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.1
-
- 1.7
- 1.7
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+ 1.4
+
+
+
+ testCompile
+
+
+
+
+
+ maven-surefire-plugin
+ 2.6
+
+ false
+
+ **/*Spec.java
+
+
+
+
+
@@ -161,6 +185,43 @@
1.12.6
provided
+
+
+ org.spockframework
+ spock-core
+ ${spock.version}
+ test
+
+
+ org.spockframework
+ spock-spring
+ ${spock.version}
+ test
+
+
+ cglib
+ cglib-nodep
+ 3.1
+ test
+
+
+ org.objenesis
+ objenesis
+ 2.1
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ 1.3
+ test
+
+
+ org.codehaus.groovy
+ groovy-all
+ 2.4.3
+ test
+
@@ -171,6 +232,7 @@
1.0.1.BUILD-SNAPSHOT
2.7.0
2.0-RC9
+ 1.0-groovy-2.4
diff --git a/spring-cloud-zookeeper-bus/pom.xml b/spring-cloud-zookeeper-bus/pom.xml
index 1b0fe0a6..df3ad807 100644
--- a/spring-cloud-zookeeper-bus/pom.xml
+++ b/spring-cloud-zookeeper-bus/pom.xml
@@ -16,6 +16,15 @@
..
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+
org.springframework.cloud
diff --git a/spring-cloud-zookeeper-bus/src/main/java/org/springframework/cloud/zookeeper/bus/SimpleRemoteEvent.java b/spring-cloud-zookeeper-bus/src/main/java/org/springframework/cloud/zookeeper/bus/SimpleRemoteEvent.java
index 3d567176..ddc8a1fc 100644
--- a/spring-cloud-zookeeper-bus/src/main/java/org/springframework/cloud/zookeeper/bus/SimpleRemoteEvent.java
+++ b/spring-cloud-zookeeper-bus/src/main/java/org/springframework/cloud/zookeeper/bus/SimpleRemoteEvent.java
@@ -11,17 +11,18 @@ import org.springframework.cloud.bus.event.RemoteApplicationEvent;
@Data
public class SimpleRemoteEvent extends RemoteApplicationEvent {
- private String message;
+ private String message;
- private SimpleRemoteEvent(){}
+ private SimpleRemoteEvent() {
+ }
- public SimpleRemoteEvent(Object source, String originService, String destinationService, String message) {
- super(source, originService, destinationService);
- this.message = message;
- }
+ public SimpleRemoteEvent(Object source, String originService, String destinationService, String message) {
+ super(source, originService, destinationService);
+ this.message = message;
+ }
- public SimpleRemoteEvent(Object source, String originService, String message) {
- super(source, originService);
- this.message = message;
- }
+ public SimpleRemoteEvent(Object source, String originService, String message) {
+ super(source, originService);
+ this.message = message;
+ }
}
diff --git a/spring-cloud-zookeeper-config/pom.xml b/spring-cloud-zookeeper-config/pom.xml
index 3ba979e0..a32f8a9a 100644
--- a/spring-cloud-zookeeper-config/pom.xml
+++ b/spring-cloud-zookeeper-config/pom.xml
@@ -16,6 +16,15 @@
..
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+
org.springframework.cloud
diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java
index 9ab7a72b..0dfd46ce 100644
--- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java
+++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySource.java
@@ -42,16 +42,14 @@ public class ZookeeperPropertySource extends EnumerablePropertySource entry : children.entrySet()) {
ChildData child = entry.getValue();
- if (child.getData()==null || child.getData().length == 0) {
+ if (child.getData() == null || child.getData().length == 0) {
findKeys(keys, child.getPath());
- }
- else {
+ } else {
keys.add(child.getPath().replace(context + "/", "").replace('/', '.'));
}
}
diff --git a/spring-cloud-zookeeper-core/pom.xml b/spring-cloud-zookeeper-core/pom.xml
index 1f2f3119..0a973323 100644
--- a/spring-cloud-zookeeper-core/pom.xml
+++ b/spring-cloud-zookeeper-core/pom.xml
@@ -16,6 +16,19 @@
..
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+
+
+
+
org.springframework.boot
@@ -49,7 +62,37 @@
spring-boot-starter-test
test
-
+
+
+ org.spockframework
+ spock-core
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ cglib
+ cglib-nodep
+ test
+
+
+ org.objenesis
+ objenesis
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ test
+
+
+ org.codehaus.groovy
+ groovy-all
+ test
+
diff --git a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java
index c2d8596e..10140cf1 100644
--- a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java
+++ b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java
@@ -1,21 +1,26 @@
package org.springframework.cloud.zookeeper;
-import javax.annotation.PreDestroy;
-
+import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import javax.annotation.PreDestroy;
+
/**
* @author Spencer Gibb
*/
@Configuration
@EnableConfigurationProperties
public class ZookeeperAutoConfiguration {
+
+ private @Autowired RetryPolicy retryPolicy;
+
@Bean
@ConditionalOnMissingBean
public ZookeeperProperties zookeeperProperties() {
@@ -26,9 +31,7 @@ public class ZookeeperAutoConfiguration {
@ConditionalOnMissingBean
public CuratorFramework curatorFramework() {
CuratorFramework curator = CuratorFrameworkFactory.builder()
- // TODO: configurable retry policy
- .retryPolicy(new ExponentialBackoffRetry(1000, 3))
- // .retryPolicy(new RetryOneTime(100))
+ .retryPolicy(retryPolicy)
// TODO: support ensembleProvider via ExhibitorEnsembleProvider
// .ensembleProvider(new ExhibitorEnsembleProvider())
.connectString(zookeeperProperties().getConnectString()).build();
@@ -41,6 +44,14 @@ public class ZookeeperAutoConfiguration {
curatorFramework().close();
}
+ @Bean
+ @ConditionalOnMissingBean
+ public RetryPolicy exponentialBackoffRetry() {
+ return new ExponentialBackoffRetry(zookeeperProperties().getBaseSleepTimeMs(),
+ zookeeperProperties().getMaxRetries(),
+ zookeeperProperties().getMaxSleepMs());
+ }
+
@Bean
@ConditionalOnMissingBean
public ZookeeperEndpoint zookeeperEndpoint() {
diff --git a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java
index 3010dfbe..150a2ee6 100644
--- a/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java
+++ b/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperProperties.java
@@ -1,11 +1,10 @@
package org.springframework.cloud.zookeeper;
-import javax.validation.constraints.NotNull;
-
import lombok.Data;
-
import org.springframework.boot.context.properties.ConfigurationProperties;
+import javax.validation.constraints.NotNull;
+
/**
* @author Spencer Gibb
*/
@@ -16,4 +15,20 @@ public class ZookeeperProperties {
private String connectString = "localhost:2181";
private boolean enabled = true;
+
+ /**
+ * @param baseSleepTimeMs initial amount of time to wait between retries
+ */
+ private Integer baseSleepTimeMs = 50;
+
+ /**
+ * @param maxRetries max number of times to retry
+ */
+ private Integer maxRetries = 50;
+
+ /**
+ * @param maxSleepMs max time in ms to sleep on each retry
+ */
+ private Integer maxSleepMs = 500;
+
}
diff --git a/spring-cloud-zookeeper-core/src/test/groovy/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationSpec.groovy b/spring-cloud-zookeeper-core/src/test/groovy/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationSpec.groovy
new file mode 100644
index 00000000..e210937d
--- /dev/null
+++ b/spring-cloud-zookeeper-core/src/test/groovy/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationSpec.groovy
@@ -0,0 +1,37 @@
+package org.springframework.cloud.zookeeper
+
+import org.apache.curator.framework.CuratorFramework
+import org.apache.curator.test.TestingServer
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.Bean
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Specification
+
+/**
+ * @author Spencer Gibb
+ */
+@ContextConfiguration(classes = [ TestConfig, ZookeeperAutoConfiguration ])
+class ZookeeperAutoConfigurationSpec extends Specification {
+
+ @Autowired(required = false)
+ CuratorFramework curator
+
+ def 'should successfully inject Curator as a Spring bean'() {
+ expect:
+ curator != null
+ }
+
+ static class TestConfig {
+ @Bean
+ ZookeeperProperties zookeeperProperties() throws Exception {
+ ZookeeperProperties properties = new ZookeeperProperties()
+ properties.connectString = testingServer().connectString
+ return properties
+ }
+
+ @Bean
+ TestingServer testingServer() throws Exception {
+ return new TestingServer()
+ }
+ }
+}
diff --git a/spring-cloud-zookeeper-core/src/test/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationTests.java b/spring-cloud-zookeeper-core/src/test/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationTests.java
deleted file mode 100644
index a7f754cf..00000000
--- a/spring-cloud-zookeeper-core/src/test/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfigurationTests.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.springframework.cloud.zookeeper;
-
-import static org.junit.Assert.assertNotNull;
-
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.test.TestingServer;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-/**
- * @author Spencer Gibb
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = { ZookeeperAutoConfigurationTests.TestConfig.class,
- ZookeeperAutoConfiguration.class })
-public class ZookeeperAutoConfigurationTests {
-
- @Autowired(required = false)
- CuratorFramework curator;
-
- @Test
- public void testZookeeperFramework() {
- assertNotNull("curator is null", curator);
- }
-
- static class TestConfig {
- @Bean
- public ZookeeperProperties zookeeperProperties() throws Exception {
- ZookeeperProperties properties = new ZookeeperProperties();
- properties.setConnectString(testingServer().getConnectString());
- return properties;
- }
-
- @Bean
- public TestingServer testingServer() throws Exception {
- return new TestingServer();
- }
- }
-}
diff --git a/spring-cloud-zookeeper-discovery/pom.xml b/spring-cloud-zookeeper-discovery/pom.xml
index f11b53a2..33c1dfc1 100644
--- a/spring-cloud-zookeeper-discovery/pom.xml
+++ b/spring-cloud-zookeeper-discovery/pom.xml
@@ -16,6 +16,22 @@
..
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+
+
+ maven-surefire-plugin
+
+
+
+
org.springframework.cloud
@@ -52,6 +68,48 @@
spring-boot-starter-test
test
+
+ org.apache.curator
+ curator-test
+ test
+
+
+
+ org.spockframework
+ spock-core
+ test
+
+
+ org.spockframework
+ spock-spring
+ test
+
+
+ cglib
+ cglib-nodep
+ test
+
+
+ org.objenesis
+ objenesis
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ test
+
+
+ org.codehaus.groovy
+ groovy-all
+ test
+
+
+ com.github.tomakehurst
+ wiremock
+ test
+ 1.53
+
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/AddressProviderConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/AddressProviderConfiguration.java
new file mode 100644
index 00000000..56efb673
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/AddressProviderConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+
+/**
+ * Configuration that registers a bean related to microservice's address and port providing.
+ *
+ * @see MicroserviceAddressProvider
+ *
+ * @author Marcin Grzejszczak, 4financeIT
+ * @author Tomasz Dziurko, 4financeIT
+ */
+@Configuration
+public class AddressProviderConfiguration {
+
+ @Autowired
+ private Environment environment;
+
+ @Bean
+ MicroserviceAddressProvider microserviceAddressProvider() {
+ String microserviceHost = environment.getProperty("microservice.host", getIpAddress());
+ Integer microservicePort = Integer.valueOf(environment.getProperty("server.port", "8080"));
+ return new MicroserviceAddressProvider(microserviceHost, microservicePort);
+ }
+
+ /**
+ * Return a non loopback IPv4 address for the machine running this process.
+ * If the machine has multiple network interfaces, the IP address for the
+ * first interface returned by {@link java.net.NetworkInterface#getNetworkInterfaces}
+ * is returned.
+ *
+ * @return non loopback IPv4 address for the machine running this process
+ * @see java.net.NetworkInterface#getNetworkInterfaces
+ * @see java.net.NetworkInterface#getInetAddresses
+ */
+ public static String getIpAddress() {
+ try {
+ for (Enumeration enumNic = NetworkInterface.getNetworkInterfaces();
+ enumNic.hasMoreElements(); ) {
+ NetworkInterface ifc = enumNic.nextElement();
+ if (ifc.isUp()) {
+ for (Enumeration enumAddr = ifc.getInetAddresses();
+ enumAddr.hasMoreElements(); ) {
+ InetAddress address = enumAddr.nextElement();
+ if (address instanceof Inet4Address && !address.isLoopbackAddress()) {
+ return address.getHostAddress();
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ return "unknown";
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/MicroserviceAddressProvider.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/MicroserviceAddressProvider.java
new file mode 100644
index 00000000..897bbc78
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/MicroserviceAddressProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery;
+
+/**
+ * Holder for microservice's host and port
+ *
+ * @author Marcin Grzejszczak, 4financeIT
+ * @author Adam Chudzik, 4financeIT
+ *
+ */
+public class MicroserviceAddressProvider {
+ private final String host;
+ private final int port;
+
+ public MicroserviceAddressProvider(String microserviceHost, int microservicePort) {
+ this.host = microserviceHost;
+ this.port = microservicePort;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/RibbonZookeeperAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/RibbonZookeeperAutoConfiguration.java
index f45f1c19..0861194e 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/RibbonZookeeperAutoConfiguration.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/RibbonZookeeperAutoConfiguration.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClient.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClient.java
index 30249953..c32efb6e 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClient.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClient.java
@@ -1,22 +1,23 @@
package org.springframework.cloud.zookeeper.discovery;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
import lombok.SneakyThrows;
-
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.context.ApplicationContext;
-import static org.springframework.util.ReflectionUtils.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* @author Spencer Gibb
+ * @author Marcin Grzejszczak, 4financeIT
*/
public class ZookeeperDiscoveryClient implements DiscoveryClient {
@@ -29,6 +30,9 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
@Autowired
ServiceDiscovery discovery;
+ @Autowired(required = false)
+ ZookeeperDependencies zookeeperDependencies;
+
@Override
public String description() {
return "Spring Cloud Zookeeper Discovery Client";
@@ -59,18 +63,26 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
@SneakyThrows
public List getInstances(
final String serviceId) {
+ String serviceIdToQuery = getServiceIdToQuery(serviceId);
Collection> zkInstances = discovery
- .queryForInstances(serviceId);
+ .queryForInstances(serviceIdToQuery);
ArrayList instances = new ArrayList<>();
for (ServiceInstance instance : zkInstances) {
- instances.add(createServiceInstance(serviceId, instance));
+ instances.add(createServiceInstance(serviceIdToQuery, instance));
}
return instances;
}
+ private String getServiceIdToQuery(String serviceId) {
+ if (zookeeperDependencies != null && zookeeperDependencies.hasDependencies()) {
+ return zookeeperDependencies.getPathForAlias(serviceId);
+ }
+ return serviceId;
+ }
+
@Override
public List getServices() {
ArrayList services = null;
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java
index 08e35d15..e4a82e53 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryClientConfiguration.java
@@ -8,6 +8,7 @@ import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -19,6 +20,7 @@ import org.springframework.core.env.Environment;
* @author Spencer Gibb
*/
@Configuration
+@Import(AddressProviderConfiguration.class)
@EnableConfigurationProperties
public class ZookeeperDiscoveryClientConfiguration {
@Autowired
@@ -40,13 +42,14 @@ public class ZookeeperDiscoveryClientConfiguration {
}
@Bean
- public ServiceInstance serviceInstance() throws Exception {
+ @ConditionalOnMissingBean
+ public ServiceInstance serviceInstance(MicroserviceAddressProvider microserviceAddressProvider) throws Exception {
Environment environment = context.getEnvironment();
- Integer port = new Integer(environment.getProperty("server.port", "8080"));
UriSpec uriSpec = new UriSpec(zookeeperDiscoveryProperties().getUriSpec());
return ServiceInstance. builder()
.name(environment.getProperty("spring.application.name"))
- .payload(new ZookeeperInstance(context.getId())).port(port)
+ .payload(new ZookeeperInstance(context.getId())).port(microserviceAddressProvider.getPort())
+ .address(microserviceAddressProvider.getHost())
.uriSpec(uriSpec).build();
}
@@ -56,15 +59,17 @@ public class ZookeeperDiscoveryClientConfiguration {
}
@Bean
- public ServiceDiscovery serviceDiscovery(CuratorFramework curator)
+ @ConditionalOnMissingBean
+ public ServiceDiscovery serviceDiscovery(CuratorFramework curator, ServiceInstance serviceInstance)
throws Exception {
return ServiceDiscoveryBuilder.builder(ZookeeperInstance.class).client(curator)
.basePath(zookeeperDiscoveryProperties().getRoot())
- .serializer(instanceSerializer()).thisInstance(serviceInstance()).build();
+ .serializer(instanceSerializer()).thisInstance(serviceInstance).build();
}
@Bean
public ZookeeperDiscoveryHealthIndicator zookeeperDiscoveryHealthIndicator() {
return new ZookeeperDiscoveryHealthIndicator();
}
+
}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryProperties.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryProperties.java
index f79c2216..8f466386 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryProperties.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryProperties.java
@@ -15,4 +15,9 @@ public class ZookeeperDiscoveryProperties {
private String root = "/services";
private String uriSpec = "{scheme}://{address}:{port}";
+
+ /**
+ * @param realm allows you to register a service under specified realm
+ */
+ private String realm;
}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java
index df398df8..8f8e78fb 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperRibbonClientConfiguration.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -16,23 +16,26 @@
package org.springframework.cloud.zookeeper.discovery;
-import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
-import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
-
-import javax.annotation.PostConstruct;
-
-import org.apache.curator.x.discovery.ServiceDiscovery;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
import com.netflix.client.config.IClientConfig;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import com.netflix.loadbalancer.ServerList;
+import org.apache.curator.x.discovery.ServiceDiscovery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.zookeeper.discovery.dependency.DependenciesPassedCondition;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+
+import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
+import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
/**
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
@@ -41,6 +44,7 @@ import com.netflix.loadbalancer.ServerList;
*
* @author Spencer Gibb
* @author Dave Syer
+ * @author Marcin Grzejszczak, 4financeIT
*/
@Configuration
public class ZookeeperRibbonClientConfiguration {
@@ -54,6 +58,16 @@ public class ZookeeperRibbonClientConfiguration {
public ZookeeperRibbonClientConfiguration() {
}
+ @Bean
+ @ConditionalOnMissingBean
+ @Conditional(DependenciesPassedCondition.class)
+ @ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
+ public ServerList> ribbonServerListFromDependencies(IClientConfig config, ZookeeperDependencies zookeeperDependencies) {
+ ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
+ serverList.initFromDependencies(config, zookeeperDependencies);
+ return serverList;
+ }
+
@Bean
@ConditionalOnMissingBean
public ServerList> ribbonServerList(IClientConfig config) {
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServerList.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServerList.java
index bb0fb9cb..d44c7730 100644
--- a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServerList.java
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/ZookeeperServerList.java
@@ -1,20 +1,21 @@
package org.springframework.cloud.zookeeper.discovery;
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.AbstractServerList;
+import org.apache.curator.x.discovery.ServiceDiscovery;
+import org.apache.curator.x.discovery.ServiceInstance;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import org.apache.curator.x.discovery.ServiceDiscovery;
-import org.apache.curator.x.discovery.ServiceInstance;
-
-import com.netflix.client.config.IClientConfig;
-import com.netflix.loadbalancer.AbstractServerList;
-
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
* @author Spencer Gibb
+ * @author Marcin Grzejszczak, 4financeIT
*/
public class ZookeeperServerList extends AbstractServerList {
@@ -30,6 +31,10 @@ public class ZookeeperServerList extends AbstractServerList {
this.serviceId = clientConfig.getClientName();
}
+ public void initFromDependencies(IClientConfig clientConfig, ZookeeperDependencies zookeeperDependencies) {
+ this.serviceId = zookeeperDependencies.getPathForAlias(clientConfig.getClientName());
+ }
+
@Override
public List getInitialListOfServers() {
return getServers();
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesPassedCondition.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesPassedCondition.java
new file mode 100644
index 00000000..f4fc624d
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/DependenciesPassedCondition.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.dependency;
+
+import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
+import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
+import org.springframework.boot.bind.RelaxedPropertyResolver;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+import java.util.Map;
+
+/**
+ * @author Marcin Grzejszczak, 4financeIT
+ */
+public class DependenciesPassedCondition extends SpringBootCondition {
+
+ private static final String ZOOKEEPER_DEPENDENCIES_PROP = "zookeeper.dependencies";
+
+ @Override
+ public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ Map subProperties = new RelaxedPropertyResolver(context.getEnvironment()).getSubProperties(ZOOKEEPER_DEPENDENCIES_PROP);
+ return subProperties.isEmpty() ?
+ ConditionOutcome.noMatch("No dependencies have been passed for the service") :
+ ConditionOutcome.match();
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java
new file mode 100644
index 00000000..139f3e80
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/LoadBalancerType.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.dependency;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.Predicate;
+
+import java.util.Arrays;
+
+import static org.apache.commons.lang.StringUtils.EMPTY;
+import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
+
+/**
+ * @author Marcin Grzejszczak, 4financeIT
+ */
+public enum LoadBalancerType {
+ STICKY, RANDOM, ROUND_ROBIN;
+
+ public static LoadBalancerType fromName(final String strategyName) {
+ LoadBalancerType loadBalancerType = (LoadBalancerType) CollectionUtils.find(Arrays.asList(values()), new Predicate() {
+ @Override
+ public boolean evaluate(Object o) {
+ LoadBalancerType input = (LoadBalancerType) o;
+ return input.name().equals(defaultIfEmpty(strategyName, EMPTY).toUpperCase());
+ }
+ });
+ if (loadBalancerType == null) {
+ return ROUND_ROBIN;
+ }
+ return loadBalancerType;
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java
new file mode 100644
index 00000000..763a4991
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependencies.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.dependency;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author Marcin Grzejszczak, 4financeIT
+ */
+@Data
+@ConfigurationProperties("zookeeper")
+public class ZookeeperDependencies {
+
+ private String prefix = "";
+
+ private Map dependencies = new LinkedHashMap<>();
+
+ @PostConstruct
+ public void init() {
+ for (Map.Entry entry : this.dependencies.entrySet()) {
+ ZookeeperDependency value = entry.getValue();
+ if (StringUtils.hasText(prefix)) {
+ value.path = prefix + value.path;
+ }
+ }
+ }
+
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class ZookeeperDependency {
+
+ private String id;
+
+ private String path;
+
+ private LoadBalancerType loadBalancerType;
+
+ private String contentTypeTemplate;
+
+ private String version;
+
+ private Map headers;
+
+ private boolean required;
+ }
+
+ public Collection getDependencyConfigurations() {
+ return dependencies.values();
+ }
+
+ public boolean hasDependencies() {
+ return !dependencies.isEmpty();
+ }
+
+ public String getPathForAlias(final String alias) {
+ for (Map.Entry zookeeperDependencyEntry : dependencies.entrySet()) {
+ if (zookeeperDependencyEntry.getKey().equals(alias)) {
+ return zookeeperDependencyEntry.getValue().getPath();
+ }
+ }
+ return "";
+ }
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java
new file mode 100644
index 00000000..efeec4d7
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/dependency/ZookeeperDependenciesAutoConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.dependency;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+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.zookeeper.ZookeeperAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Provides autoconfiguration for Zookeeper dependency set up in properties.
+ *
+ * @see ZookeeperDependencies
+ *
+ * @author Marcin Grzejszczak, 4financeIT
+ *
+ */
+@Configuration
+@EnableConfigurationProperties
+@Conditional(DependenciesPassedCondition.class)
+@ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
+@AutoConfigureAfter(ZookeeperAutoConfiguration.class)
+public class ZookeeperDependenciesAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ZookeeperDependencies zookeeperDependencies() {
+ return new ZookeeperDependencies();
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcher.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcher.java
new file mode 100755
index 00000000..d3ef8f24
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcher.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher;
+
+import org.apache.curator.x.discovery.ServiceCache;
+import org.apache.curator.x.discovery.ServiceDiscovery;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies.ZookeeperDependency;
+import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Marcin Grzejszczak, 4financeIT
+ * @author Michal Chmielarz, 4financeIT
+ */
+public class DefaultDependencyWatcher implements DependencyRegistrationHookProvider {
+
+ private final ServiceDiscovery serviceDiscovery;
+ private final Map dependencyRegistry = new HashMap<>();
+ private final List listeners;
+ private final DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier;
+ private final ZookeeperDependencies zookeeperDependencies;
+
+ public DefaultDependencyWatcher(ServiceDiscovery serviceDiscovery,
+ DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
+ List dependencyWatcherListeners,
+ ZookeeperDependencies zookeeperDependencies) {
+ this.serviceDiscovery = serviceDiscovery;
+ this.dependencyPresenceOnStartupVerifier = dependencyPresenceOnStartupVerifier;
+ this.listeners = dependencyWatcherListeners;
+ this.zookeeperDependencies = zookeeperDependencies;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void registerDependencyRegistrationHooks() throws Exception {
+ for (ZookeeperDependency zookeeperDependency : zookeeperDependencies.getDependencyConfigurations()) {
+ String dependencyPath = zookeeperDependency.getPath();
+ ServiceCache serviceCache = serviceDiscovery.serviceCacheBuilder().name(dependencyPath).build();
+ serviceCache.start();
+ dependencyPresenceOnStartupVerifier.verifyDependencyPresence(dependencyPath, serviceCache, zookeeperDependency.isRequired());
+ dependencyRegistry.put(dependencyPath, serviceCache);
+ serviceCache.addListener(new DependencyStateChangeListenerRegistry(listeners, dependencyPath, serviceCache));
+ }
+ }
+
+ @Override
+ public void clearDependencyRegistrationHooks() throws IOException {
+ for (ServiceCache cache : dependencyRegistry.values()) {
+ cache.close();
+ }
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyRegistrationHookProvider.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyRegistrationHookProvider.java
new file mode 100644
index 00000000..1b60fbc0
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyRegistrationHookProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher;
+
+import java.io.IOException;
+
+/**
+ * @author listeners;
+ private final String dependencyName;
+ private final ServiceCache serviceCache;
+
+ public DependencyStateChangeListenerRegistry(List listeners, String dependencyName, ServiceCache serviceCache) {
+ this.listeners = listeners;
+ this.dependencyName = dependencyName;
+ this.serviceCache = serviceCache;
+ }
+
+ @Override
+ public void cacheChanged() {
+ DependencyState state = serviceCache.getInstances().isEmpty() ? DependencyState.DISCONNECTED : DependencyState.CONNECTED;
+ logCurrentState(state);
+ informListeners(state);
+ }
+
+ private void logCurrentState(DependencyState dependencyState) {
+ log.info("Service cache state change for '{}' instances, current service state: {}", dependencyName, dependencyState);
+ }
+
+ private void informListeners(DependencyState state) {
+ for (DependencyWatcherListener listener : listeners) {
+ listener.stateChanged(dependencyName, state);
+ }
+ }
+
+ @Override
+ public void stateChanged(CuratorFramework client, ConnectionState newState) {
+ // todo do something or ignore for what is worth
+ }
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcher.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcher.java
new file mode 100644
index 00000000..6284cd9e
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcher.java
@@ -0,0 +1,34 @@
+package org.springframework.cloud.zookeeper.discovery.watcher;
+
+import java.io.IOException;
+
+public interface DependencyWatcher {
+
+ /**
+ * Register hooks upon dependencies registration
+ *
+ * @throws Exception
+ */
+ void registerDependencyRegistrationHooks() throws Exception;
+
+ /**
+ * Unregister hooks upon dependencies registration
+ *
+ * @throws IOException
+ */
+ void clearDependencyRegistrationHooks() throws IOException;
+
+ /**
+ * Register a listener for a dependency
+ *
+ * @param listener
+ */
+ void registerDependencyStateChangeListener(DependencyWatcherListener listener);
+
+ /**
+ * Unregister a listener for a dependency
+ *
+ * @param listener
+ */
+ void clearDependencyStateChangeListener(DependencyWatcherListener listener);
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherAutoConfiguration.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherAutoConfiguration.java
new file mode 100644
index 00000000..a0b62a1c
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherAutoConfiguration.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher;
+
+import org.apache.curator.x.discovery.ServiceDiscovery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+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.zookeeper.discovery.dependency.DependenciesPassedCondition;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
+import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependenciesAutoConfiguration;
+import org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier;
+import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides hooks for observing dependency lifecycle in Zookeeper.
+ * Needs custom dependencies to be set in order to work.
+ *
+ * @see ZookeeperDependencies
+ *
+ * @author Marcin Grzejszczak, 4financeIT
+ */
+@Configuration
+@EnableConfigurationProperties
+@Conditional(DependenciesPassedCondition.class)
+@ConditionalOnProperty(value = "zookeeper.dependencies.enabled", matchIfMissing = true)
+@AutoConfigureAfter(ZookeeperDependenciesAutoConfiguration.class)
+public class DependencyWatcherAutoConfiguration {
+
+ @Autowired(required = false)
+ private List dependencyWatcherListeners = new ArrayList<>();
+
+ @Bean
+ @ConditionalOnMissingBean
+ public DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier() {
+ return new DefaultDependencyPresenceOnStartupVerifier();
+ }
+
+ @Bean(initMethod = "registerDependencyRegistrationHooks", destroyMethod = "clearDependencyRegistrationHooks")
+ @ConditionalOnMissingBean
+ public DependencyRegistrationHookProvider dependencyWatcher(ServiceDiscovery serviceDiscovery,
+ DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
+ ZookeeperDependencies zookeeperDependencies) {
+ return new DefaultDependencyWatcher(serviceDiscovery,
+ dependencyPresenceOnStartupVerifier,
+ dependencyWatcherListeners,
+ zookeeperDependencies);
+ }
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherListener.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherListener.java
new file mode 100755
index 00000000..a24ae717
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/DependencyWatcherListener.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher;
+
+/**
+ * Performs logic upon change of state of a dependency {@see DependencyState}
+ * in the service discovery system.
+ *
+ * @author serviceInstances) {
+ if (serviceInstances.isEmpty()) {
+ throw new NoInstancesRunningException(dependencyName);
+ }
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/LogMissingDependencyChecker.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/LogMissingDependencyChecker.java
new file mode 100755
index 00000000..1808fbcd
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/LogMissingDependencyChecker.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher.presence;
+
+import org.apache.curator.x.discovery.ServiceInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+
+/**
+ * @author Marcin Grzejszczak, 4financeIT
+ * @author Tomasz Dziurko, 4financeIT
+ */
+public class LogMissingDependencyChecker implements PresenceChecker {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Override
+ public void checkPresence(String dependencyName, List serviceInstances) {
+ if (serviceInstances.isEmpty()) {
+ log.warn("Microservice dependency with name [" + dependencyName + "] is missing.");
+ }
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/NoInstancesRunningException.java b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/NoInstancesRunningException.java
new file mode 100755
index 00000000..5810b803
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/main/java/org/springframework/cloud/zookeeper/discovery/watcher/presence/NoInstancesRunningException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher.presence;
+
+/**
+ * @author instances = discoveryClient.getInstances(TEST_INSTANCE_NAME)
+ ServiceInstance instance = instances.first()
+ expect:
+ 'pong' == testRibbonClient.pingOnUrl("${instance.host}:${instance.port}")
+ }
+
+ def 'should properly find local instance'() {
+ expect:
+ AddressProviderConfiguration.ipAddress == discoveryClient.localServiceInstance.host
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ @Import(CommonTestConfig)
+ @EnableDiscoveryClient
+ static class Config {
+
+ @Bean
+ TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,
+ @Value('${spring.application.name}') String springAppName) {
+ return new TestRibbonClient(restTemplate, springAppName)
+ }
+
+ }
+
+ static class TestRibbonClient extends TestServiceRestClient {
+
+ private final String thisAppName
+
+ TestRibbonClient(RestTemplate restTemplate, String thisAppName) {
+ super(restTemplate)
+ this.thisAppName = thisAppName
+ }
+
+ String thisHealthCheck() {
+ return restTemplate.getForObject("http://$thisAppName/health", String)
+ }
+
+ }
+}
diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryWithDependenciesISpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryWithDependenciesISpec.groovy
new file mode 100644
index 00000000..0feab1c0
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/ZookeeperDiscoveryWithDependenciesISpec.groovy
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery
+
+import com.github.tomakehurst.wiremock.WireMockServer
+import com.github.tomakehurst.wiremock.client.WireMock
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.SpringApplicationContextLoader
+import org.springframework.cloud.client.ServiceInstance
+import org.springframework.cloud.client.discovery.DiscoveryClient
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient
+import org.springframework.cloud.client.loadbalancer.LoadBalanced
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.Import
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.web.client.RestTemplate
+import spock.lang.Specification
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*
+
+@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader)
+@ActiveProfiles('watcher')
+class ZookeeperDiscoveryWithDependenciesISpec extends Specification {
+
+ @Autowired TestRibbonClient testRibbonClient
+ @Autowired WireMockServer wiremockServer
+ @Autowired DiscoveryClient discoveryClient
+ WireMock wireMock
+
+ def setup() {
+ wireMock = new WireMock('localhost', wiremockServer.port())
+ wireMock.register(get(urlEqualTo('/ping')).willReturn(aResponse().withBody('pong')))
+ }
+
+ def 'should find a collaborator via Ribbon by using its alias from dependencies'() {
+ expect:
+ 'pong' == testRibbonClient.pingService('someAlias')
+ }
+
+ def 'should find a collaborator via discovery client'() {
+ given:
+ List instances = discoveryClient.getInstances('someAlias')
+ ServiceInstance instance = instances.first()
+ expect:
+ 'pong' == testRibbonClient.pingOnUrl("${instance.host}:${instance.port}")
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ @Import(CommonTestConfig)
+ @EnableDiscoveryClient
+ static class Config {
+
+ @Bean
+ TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate) {
+ return new TestRibbonClient(restTemplate)
+ }
+
+ }
+
+ static class TestRibbonClient extends TestServiceRestClient {
+
+ TestRibbonClient(RestTemplate restTemplate) {
+ super(restTemplate)
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcherSpringISpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcherSpringISpec.groovy
new file mode 100644
index 00000000..3245501a
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/DefaultDependencyWatcherSpringISpec.groovy
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher
+
+import org.apache.curator.framework.CuratorFramework
+import org.apache.curator.framework.CuratorFrameworkFactory
+import org.apache.curator.retry.ExponentialBackoffRetry
+import org.apache.curator.test.TestingServer
+import org.apache.curator.x.discovery.*
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.SpringApplicationContextLoader
+import org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier
+import org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.util.SocketUtils
+import spock.lang.Specification
+import spock.util.concurrent.PollingConditions
+
+@ContextConfiguration(classes = Config, loader = SpringApplicationContextLoader)
+@ActiveProfiles('watcher')
+class DefaultDependencyWatcherSpringISpec extends Specification {
+
+ @Autowired AssertableDependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier
+ @Autowired AssertableDependencyWatcherListener dependencyWatcherListener
+ @Autowired ServiceDiscovery serviceDiscovery
+ @Autowired ServiceInstance serviceInstance
+
+ def 'should verify that presence of a dependency has been checked'() {
+ expect:
+ dependencyPresenceOnStartupVerifier.startupPresenceVerified
+ }
+
+ def 'should verify that dependency watcher listener is successfully registered and operational'() {
+ when:
+ serviceDiscovery.unregisterService(serviceInstance)
+ then:
+ new PollingConditions().eventually {
+ dependencyWatcherListener.dependencyState == DependencyState.DISCONNECTED
+ }
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ static class Config {
+
+ @Bean
+ static PropertySourcesPlaceholderConfigurer propertiesConfigurer() {
+ return new PropertySourcesPlaceholderConfigurer()
+ }
+
+ @Bean(destroyMethod = 'close')
+ TestingServer testingServer() {
+ return new TestingServer(SocketUtils.findAvailableTcpPort())
+ }
+
+ @Bean
+ ServiceInstance serviceInstance() {
+ return ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
+ .address('anyUrl')
+ .port(10)
+ .name('testInstance')
+ .build()
+ }
+
+ @Bean(initMethod = 'start', destroyMethod = 'close')
+ ServiceDiscovery serviceDiscovery() {
+ return ServiceDiscoveryBuilder
+ .builder(Void)
+ .basePath('/')
+ .client(curatorFramework())
+ .thisInstance(serviceInstance())
+ .build()
+ }
+
+ @Bean(initMethod = 'start', destroyMethod = 'close')
+ CuratorFramework curatorFramework() {
+ return CuratorFrameworkFactory.newClient(testingServer().connectString, new ExponentialBackoffRetry(20, 20, 500))
+ }
+
+ @Bean
+ DependencyWatcherListener dependencyWatcherListener() {
+ return new AssertableDependencyWatcherListener()
+ }
+
+ @Bean
+ DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier() {
+ return new AssertableDependencyPresenceOnStartupVerifier()
+ }
+
+ }
+
+ static class AssertableDependencyWatcherListener implements DependencyWatcherListener {
+
+ DependencyState dependencyState = DependencyState.CONNECTED
+
+ @Override
+ void stateChanged(String dependencyName, DependencyState newState) {
+ dependencyState = newState
+ }
+ }
+
+ static class AssertableDependencyPresenceOnStartupVerifier extends DependencyPresenceOnStartupVerifier {
+
+ boolean startupPresenceVerified = false
+
+ AssertableDependencyPresenceOnStartupVerifier() {
+ super(new LogMissingDependencyChecker())
+ }
+
+ @Override
+ void verifyDependencyPresence(String dependencyName, ServiceCache serviceCache, boolean required) {
+ startupPresenceVerified = true
+ }
+ }
+}
diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy
new file mode 100644
index 00000000..95ae1253
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DefaultDependencyPresenceOnStartupVerifierSpec.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher.presence
+
+import org.apache.curator.x.discovery.ServiceCache
+import org.codehaus.groovy.runtime.StackTraceUtils
+import spock.lang.Specification
+
+class DefaultDependencyPresenceOnStartupVerifierSpec extends Specification {
+
+ private static final String SERVICE_NAME = 'service01'
+
+ def 'should throw exception if obligatory dependencies are missing'() {
+ given:
+ DefaultDependencyPresenceOnStartupVerifier dependencyVerifier = new DefaultDependencyPresenceOnStartupVerifier()
+ ServiceCache serviceCache = Mock()
+ serviceCache.instances >> []
+ when:
+ dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, true)
+ then:
+ Throwable thrown = thrown(Throwable)
+ StackTraceUtils.extractRootCause(thrown).class == NoInstancesRunningException
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DependencyPresenceOnStartupVerifierSpec.groovy b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DependencyPresenceOnStartupVerifierSpec.groovy
new file mode 100644
index 00000000..f8ed3809
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/groovy/org/springframework/cloud/zookeeper/discovery/watcher/presence/DependencyPresenceOnStartupVerifierSpec.groovy
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012-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.zookeeper.discovery.watcher.presence
+
+import org.apache.curator.x.discovery.ServiceCache
+import spock.lang.Specification
+
+class DependencyPresenceOnStartupVerifierSpec extends Specification {
+
+ private static final String SERVICE_NAME = 'service01'
+
+ def 'should check optional dependency using optional dependency checker'() {
+ given:
+ PresenceChecker optionalDependencyChecker = Mock()
+ DependencyPresenceOnStartupVerifier dependencyVerifier = new DependencyPresenceOnStartupVerifier(optionalDependencyChecker) {
+ }
+ ServiceCache serviceCache = Mock()
+ serviceCache.instances >> []
+ when:
+ dependencyVerifier.verifyDependencyPresence(SERVICE_NAME, serviceCache, false)
+ then:
+ 1 * optionalDependencyChecker.checkPresence(SERVICE_NAME, serviceCache.instances)
+ }
+
+}
diff --git a/spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml b/spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml
new file mode 100644
index 00000000..73852a66
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/resources/application-ribbon.yml
@@ -0,0 +1 @@
+spring.application.name: ribbonApp
\ No newline at end of file
diff --git a/spring-cloud-zookeeper-discovery/src/test/resources/application-watcher.yml b/spring-cloud-zookeeper-discovery/src/test/resources/application-watcher.yml
new file mode 100644
index 00000000..b28092a1
--- /dev/null
+++ b/spring-cloud-zookeeper-discovery/src/test/resources/application-watcher.yml
@@ -0,0 +1,20 @@
+spring.application.name: someName
+zookeeper:
+ dependencies:
+ someAlias:
+ id: someId
+ path: testInstance
+ loadBalancerType: ROUND_ROBIN
+ contentTypeTemplate: application/vnd.newsletter.$version+json
+ version: v1
+ headers:
+ header1: value1
+ header2: value2
+ required: false
+ testInstance2:
+ id: someId2
+ path: somePath2
+ loadBalancerType: ROUND_ROBIN
+ contentTypeTemplate: application/vnd.newsletter.$version+json2
+ version: v1
+ required: false
diff --git a/spring-cloud-zookeeper-sample/pom.xml b/spring-cloud-zookeeper-sample/pom.xml
index 6f1c6658..40fb7488 100644
--- a/spring-cloud-zookeeper-sample/pom.xml
+++ b/spring-cloud-zookeeper-sample/pom.xml
@@ -1,58 +1,58 @@
- 4.0.0
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
- spring-cloud-zookeeper-sample
- jar
- Spring Cloud Zookeeper Sample
- Spring Cloud Zookeeper Sample
+ spring-cloud-zookeeper-sample
+ jar
+ Spring Cloud Zookeeper Sample
+ Spring Cloud Zookeeper Sample
-
- org.springframework.cloud
- spring-cloud-zookeeper
- 1.0.0.BUILD-SNAPSHOT
- ..
-
+
+ org.springframework.cloud
+ spring-cloud-zookeeper
+ 1.0.0.BUILD-SNAPSHOT
+ ..
+
-
-
-
-
- maven-deploy-plugin
-
- true
-
-
-
-
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
-
-
- org.springframework.boot
- spring-boot-starter-web
- test
-
-
- org.springframework.cloud
- spring-cloud-zookeeper-config
- test
-
-
- org.springframework.cloud
- spring-cloud-zookeeper-discovery
- test
-
-
- org.springframework.cloud
- spring-cloud-zookeeper-bus
- test
-
-
- org.projectlombok
- lombok
- test
-
-
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-zookeeper-config
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-zookeeper-discovery
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-zookeeper-bus
+ test
+
+
+ org.projectlombok
+ lombok
+ test
+
+