Updates to current formatting standards

This commit is contained in:
Spencer Gibb
2019-02-07 13:46:37 -05:00
parent dd5b576456
commit 3fa477c7d3
107 changed files with 2245 additions and 1177 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,16 +17,18 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.EnumerablePropertySource;
/** /**
* A {@link EnumerablePropertySource} that has a notion of a context which is * A {@link EnumerablePropertySource} that has a notion of a context which is the root
* the root folder in Zookeeper. * folder in Zookeeper.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
*/ */
public abstract class AbstractZookeeperPropertySource extends EnumerablePropertySource<CuratorFramework> { public abstract class AbstractZookeeperPropertySource
extends EnumerablePropertySource<CuratorFramework> {
private String context; private String context;
@@ -45,4 +47,5 @@ public abstract class AbstractZookeeperPropertySource extends EnumerableProperty
public String getContext() { public String getContext() {
return this.context; return this.context;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,13 +16,14 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import javax.annotation.PostConstruct;
import java.io.Closeable; import java.io.Closeable;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PostConstruct;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
@@ -30,6 +31,7 @@ import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent; import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener; import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.KeeperException;
import org.springframework.cloud.endpoint.event.RefreshEvent; import org.springframework.cloud.endpoint.event.RefreshEvent;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationEventPublisherAware;
@@ -39,20 +41,25 @@ import static org.apache.curator.framework.recipes.cache.TreeCacheEvent.Type.NOD
import static org.apache.curator.framework.recipes.cache.TreeCacheEvent.Type.NODE_UPDATED; import static org.apache.curator.framework.recipes.cache.TreeCacheEvent.Type.NODE_UPDATED;
/** /**
* Class that registers a {@link TreeCache} for each context. * Class that registers a {@link TreeCache} for each context. It publishes events upon
* It publishes events upon element change in Zookeeper. * element change in Zookeeper.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
*/ */
public class ConfigWatcher implements Closeable, TreeCacheListener, ApplicationEventPublisherAware{ public class ConfigWatcher
implements Closeable, TreeCacheListener, ApplicationEventPublisherAware {
private static final Log log = LogFactory.getLog(ConfigWatcher.class); private static final Log log = LogFactory.getLog(ConfigWatcher.class);
private AtomicBoolean running = new AtomicBoolean(false); private AtomicBoolean running = new AtomicBoolean(false);
private List<String> contexts; private List<String> contexts;
private CuratorFramework source; private CuratorFramework source;
private ApplicationEventPublisher publisher; private ApplicationEventPublisher publisher;
private HashMap<String, TreeCache> caches; private HashMap<String, TreeCache> caches;
public ConfigWatcher(List<String> contexts, CuratorFramework source) { public ConfigWatcher(List<String> contexts, CuratorFramework source) {
@@ -80,9 +87,11 @@ public class ConfigWatcher implements Closeable, TreeCacheListener, ApplicationE
this.caches.put(context, cache); this.caches.put(context, cache);
// no race condition since ZookeeperAutoConfiguration.curatorFramework // no race condition since ZookeeperAutoConfiguration.curatorFramework
// calls curator.blockUntilConnected // calls curator.blockUntilConnected
} catch (KeeperException.NoNodeException e) { }
catch (KeeperException.NoNodeException e) {
// no node, ignore // no node, ignore
} catch (Exception e) { }
catch (Exception e) {
log.error("Error initializing listener for context " + context, e); log.error("Error initializing listener for context " + context, e);
} }
} }
@@ -100,10 +109,13 @@ public class ConfigWatcher implements Closeable, TreeCacheListener, ApplicationE
} }
@Override @Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception { public void childEvent(CuratorFramework client, TreeCacheEvent event)
throws Exception {
TreeCacheEvent.Type eventType = event.getType(); TreeCacheEvent.Type eventType = event.getType();
if (eventType == NODE_ADDED || eventType == NODE_REMOVED || eventType == NODE_UPDATED) { if (eventType == NODE_ADDED || eventType == NODE_REMOVED
this.publisher.publishEvent(new RefreshEvent(this, event, getEventDesc(event))); || eventType == NODE_UPDATED) {
this.publisher
.publishEvent(new RefreshEvent(this, event, getEventDesc(event)));
} }
} }
@@ -117,4 +129,5 @@ public class ConfigWatcher implements Closeable, TreeCacheListener, ApplicationE
} }
return out.toString(); return out.toString();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.endpoint.RefreshEndpoint; import org.springframework.cloud.endpoint.RefreshEndpoint;
@@ -25,8 +26,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* that registers a Zookeeper configuration watcher. * Auto-configuration} that registers a Zookeeper configuration watcher.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -39,11 +40,14 @@ public class ZookeeperConfigAutoConfiguration {
@Configuration @Configuration
@ConditionalOnClass(RefreshEndpoint.class) @ConditionalOnClass(RefreshEndpoint.class)
protected static class ZkRefreshConfiguration { protected static class ZkRefreshConfiguration {
@Bean @Bean
@ConditionalOnProperty(name = "spring.cloud.zookeeper.config.watcher.enabled", matchIfMissing = true) @ConditionalOnProperty(name = "spring.cloud.zookeeper.config.watcher.enabled", matchIfMissing = true)
public ConfigWatcher configWatcher(ZookeeperPropertySourceLocator locator, public ConfigWatcher configWatcher(ZookeeperPropertySourceLocator locator,
CuratorFramework curator) { CuratorFramework curator) {
return new ConfigWatcher(locator.getContexts(), curator); return new ConfigWatcher(locator.getContexts(), curator);
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled;
import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration; import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration;
@@ -25,7 +26,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
/** /**
* Bootstrap Configuration for Zookeeper Configuration * Bootstrap Configuration for Zookeeper Configuration.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -47,4 +48,5 @@ public class ZookeeperConfigBootstrapConfiguration {
public ZookeeperConfigProperties zookeeperConfigProperties() { public ZookeeperConfigProperties zookeeperConfigProperties() {
return new ZookeeperConfigProperties(); return new ZookeeperConfigProperties();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,7 +16,8 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import org.hibernate.validator.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -25,27 +26,27 @@ import org.springframework.validation.annotation.Validated;
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
*
* @see ZookeeperPropertySourceLocator * @see ZookeeperPropertySourceLocator
*/ */
@Validated @Validated
@ConfigurationProperties("spring.cloud.zookeeper.config") @ConfigurationProperties("spring.cloud.zookeeper.config")
public class ZookeeperConfigProperties { public class ZookeeperConfigProperties {
private boolean enabled = true; private boolean enabled = true;
/** /**
* Root folder where the configuration for Zookeeper is kept * Root folder where the configuration for Zookeeper is kept.
*/ */
private String root = "config"; private String root = "config";
/** /**
* The name of the default context * The name of the default context.
*/ */
@NotEmpty @NotEmpty
private String defaultContext = "application"; private String defaultContext = "application";
/** /**
* Separator for profile appended to the application name * Separator for profile appended to the application name.
*/ */
@NotEmpty @NotEmpty
private String profileSeparator = ","; private String profileSeparator = ",";
@@ -94,4 +95,5 @@ public class ZookeeperConfigProperties {
public void setFailFast(boolean failFast) { public void setFailFast(boolean failFast) {
this.failFast = failFast; this.failFast = failFast;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -26,11 +26,12 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.KeeperException;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* {@link org.springframework.core.env.PropertySource} that stores properties * {@link org.springframework.core.env.PropertySource} that stores properties from
* from Zookeeper inside a map. Properties are loaded upon class initialization. * Zookeeper inside a map. Properties are loaded upon class initialization.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -56,13 +57,15 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
byte[] bytes = null; byte[] bytes = null;
try { try {
bytes = this.getSource().getData().forPath(fullPath); bytes = this.getSource().getData().forPath(fullPath);
} catch (KeeperException e) { }
catch (KeeperException e) {
if (e.code() != KeeperException.Code.NONODE) { // not found if (e.code() != KeeperException.Code.NONODE) { // not found
throw e; throw e;
} }
} }
return bytes; return bytes;
} catch (Exception exception) { }
catch (Exception exception) {
ReflectionUtils.rethrowRuntimeException(exception); ReflectionUtils.rethrowRuntimeException(exception);
} }
return null; return null;
@@ -92,15 +95,18 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
if (childPathChildren == null || childPathChildren.isEmpty()) { if (childPathChildren == null || childPathChildren.isEmpty()) {
registerKeyValue(childPath, ""); registerKeyValue(childPath, "");
} }
} else { }
registerKeyValue(childPath, new String(bytes, Charset.forName("UTF-8"))); else {
registerKeyValue(childPath,
new String(bytes, Charset.forName("UTF-8")));
} }
// Check children even if we have found a value for the current znode // Check children even if we have found a value for the current znode
findProperties(childPath, childPathChildren); findProperties(childPath, childPathChildren);
} }
log.trace("leaving findProperties for path: " + path); log.trace("leaving findProperties for path: " + path);
} catch (Exception exception) { }
catch (Exception exception) {
ReflectionUtils.rethrowRuntimeException(exception); ReflectionUtils.rethrowRuntimeException(exception);
} }
} }
@@ -114,7 +120,8 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
List<String> children = null; List<String> children = null;
try { try {
children = this.getSource().getChildren().forPath(path); children = this.getSource().getChildren().forPath(path);
} catch (KeeperException e) { }
catch (KeeperException e) {
if (e.code() != KeeperException.Code.NONODE) { // not found if (e.code() != KeeperException.Code.NONODE) { // not found
throw e; throw e;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,15 +16,17 @@
package org.springframework.cloud.zookeeper.config; package org.springframework.cloud.zookeeper.config;
import javax.annotation.PreDestroy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator; import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@@ -33,13 +35,17 @@ import org.springframework.core.env.PropertySource;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* Zookeeper provides a <a href="http://zookeeper.apache.org/doc/current/zookeeperOver.html#sc_dataModelNameSpace">hierarchical namespace</a> that allows * Zookeeper provides a <a href=
* clients to store arbitrary data, such as configuration data. Spring Cloud Zookeeper Config is an alternative to the * "http://zookeeper.apache.org/doc/current/zookeeperOver.html#sc_dataModelNameSpace">hierarchical
* <a href="https://github.com/spring-cloud/spring-cloud-config">Config Server and Client</a>. Configuration is loaded into the Spring Environment during * namespace</a> that allows clients to store arbitrary data, such as configuration data.
* the special "bootstrap" phase. Configuration is stored in the {@code /config} namespace by default. Multiple * Spring Cloud Zookeeper Config is an alternative to the
* {@code PropertySource} instances are created based on the application's name and the active profiles that mimicks the Spring Cloud Config * <a href="https://github.com/spring-cloud/spring-cloud-config">Config Server and
* order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources * Client</a>. Configuration is loaded into the Spring Environment during the special
* created: * "bootstrap" phase. Configuration is stored in the {@code /config} namespace by default.
* Multiple {@code PropertySource} instances are created based on the application's name
* and the active profiles that mimicks the Spring Cloud Config order of resolving
* properties. For example, an application with the name "testApp" and with the "dev"
* profile will have the following property sources created:
* *
* <pre>{@code * <pre>{@code
* config/testApp,dev * config/testApp,dev
@@ -48,11 +54,11 @@ import org.springframework.util.ReflectionUtils;
* config/application * config/application
* }</pre> * }</pre>
* *
* </p> * The most specific property source is at the top, with the least specific at the bottom.
* The most specific property source is at the top, with the least specific at the * Properties is the {@code config/application} namespace are applicable to all
* bottom. Properties is the {@code config/application} namespace are applicable to all applications * applications using zookeeper for configuration. Properties in the
* using zookeeper for configuration. Properties in the {@code config/testApp} namespace are only available * {@code config/testApp} namespace are only available to the instances of the service
* to the instances of the service named "testApp". * named "testApp".
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -65,9 +71,11 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
private List<String> contexts; private List<String> contexts;
private static final Log log = LogFactory.getLog(ZookeeperPropertySourceLocator.class); private static final Log log = LogFactory
.getLog(ZookeeperPropertySourceLocator.class);
public ZookeeperPropertySourceLocator(CuratorFramework curator, ZookeeperConfigProperties properties) { public ZookeeperPropertySourceLocator(CuratorFramework curator,
ZookeeperConfigProperties properties) {
this.curator = curator; this.curator = curator;
this.properties = properties; this.properties = properties;
} }
@@ -84,7 +92,8 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
if (appName == null) { if (appName == null) {
// use default "application" (which config client does) // use default "application" (which config client does)
appName = "application"; appName = "application";
log.warn("spring.application.name is not set. Using default of 'application'"); log.warn(
"spring.application.name is not set. Using default of 'application'");
} }
List<String> profiles = Arrays.asList(env.getActiveProfiles()); List<String> profiles = Arrays.asList(env.getActiveProfiles());
@@ -112,11 +121,14 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
PropertySource propertySource = create(propertySourceContext); PropertySource propertySource = create(propertySourceContext);
composite.addPropertySource(propertySource); composite.addPropertySource(propertySource);
// TODO: howto call close when /refresh // TODO: howto call close when /refresh
} catch (Exception e) { }
catch (Exception e) {
if (this.properties.isFailFast()) { if (this.properties.isFailFast()) {
ReflectionUtils.rethrowRuntimeException(e); ReflectionUtils.rethrowRuntimeException(e);
} else { }
log.warn("Unable to load zookeeper config from " + propertySourceContext, e); else {
log.warn("Unable to load zookeeper config from "
+ propertySourceContext, e);
} }
} }
} }
@@ -140,4 +152,5 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
contexts.add(baseContext + this.properties.getProfileSeparator() + profile); contexts.add(baseContext + this.properties.getProfileSeparator() + profile);
} }
} }
} }

View File

@@ -1,79 +1,93 @@
/*
* Copyright 2015-2019 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.config; package org.springframework.cloud.zookeeper.config;
import java.net.ConnectException;
import org.junit.*; import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import java.net.ConnectException;
/** /**
* @author Cesar Aguilera * @author Cesar Aguilera
*/ */
public class ZookeeperConfigAutoConfigurationTests { public class ZookeeperConfigAutoConfigurationTests {
@Rule @Rule
public ExpectedException expectedException; public ExpectedException expectedException;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
expectedException = ExpectedException.none(); expectedException = ExpectedException.none();
// makes Curator fail faster, otherwise it takes 15 seconds to trigger a retry // makes Curator fail faster, otherwise it takes 15 seconds to trigger a retry
System.setProperty("curator-default-connection-timeout", "0"); System.setProperty("curator-default-connection-timeout", "0");
} }
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
System.clearProperty("curator-default-connection-timeout"); System.clearProperty("curator-default-connection-timeout");
} }
@Test(expected = NoSuchBeanDefinitionException.class) @Test(expected = NoSuchBeanDefinitionException.class)
public void testConfigEnabledFalseDoesNotLoadZookeeperConfigAutoConfiguration() throws Exception { public void testConfigEnabledFalseDoesNotLoadZookeeperConfigAutoConfiguration()
ConfigurableApplicationContext context = new SpringApplicationBuilder() throws Exception {
.sources(Config.class) ConfigurableApplicationContext context = new SpringApplicationBuilder()
.web(WebApplicationType.NONE) .sources(Config.class).web(WebApplicationType.NONE)
.run( .run("--spring.application.name=testZookeeperConfigEnabledSetToFalse",
"--spring.application.name=testZookeeperConfigEnabledSetToFalse", "--spring.jmx.default-domain=testZookeeperConfigEnabledSetToFalse",
"--spring.jmx.default-domain=testZookeeperConfigEnabledSetToFalse", "--spring.cloud.zookeeper.config.connectString=localhost:2188",
"--spring.cloud.zookeeper.config.connectString=localhost:2188", "--spring.cloud.zookeeper.baseSleepTimeMs=0",
"--spring.cloud.zookeeper.baseSleepTimeMs=0", "--spring.cloud.zookeeper.maxRetries=0",
"--spring.cloud.zookeeper.maxRetries=0", "--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.maxSleepMs=0", "--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.blockUntilConnectedWait=0", "--spring.cloud.zookeeper.config.failFast=false",
"--spring.cloud.zookeeper.config.failFast=false", "--spring.cloud.zookeeper.config.enabled=false");
"--spring.cloud.zookeeper.config.enabled=false"
);
context.getBean(ZookeeperConfigAutoConfiguration.class);
}
context.getBean(ZookeeperConfigAutoConfiguration.class); @Test
} public void testConfigEnabledTrueLoadsZookeeperConfigAutoConfiguration()
throws Exception {
expectedException.expect(ConnectException.class);
new SpringApplicationBuilder().sources(Config.class).web(WebApplicationType.NONE)
.run("--spring.application.name=testZookeeperConfigEnabledSetToTrue",
"--spring.jmx.default-domain=testZookeeperConfigEnabledSetToTrue",
"--spring.cloud.zookeeper.config.connectString=localhost:2188",
"--spring.cloud.zookeeper.baseSleepTimeMs=0",
"--spring.cloud.zookeeper.maxRetries=0",
"--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.config.failFast=false",
"--spring.cloud.zookeeper.config.enabled=true");
}
@Test @SpringBootApplication
public void testConfigEnabledTrueLoadsZookeeperConfigAutoConfiguration() throws Exception { static class Config {
expectedException.expect(ConnectException.class);
new SpringApplicationBuilder() }
.sources(Config.class)
.web(WebApplicationType.NONE)
.run(
"--spring.application.name=testZookeeperConfigEnabledSetToTrue",
"--spring.jmx.default-domain=testZookeeperConfigEnabledSetToTrue",
"--spring.cloud.zookeeper.config.connectString=localhost:2188",
"--spring.cloud.zookeeper.baseSleepTimeMs=0",
"--spring.cloud.zookeeper.maxRetries=0",
"--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.config.failFast=false",
"--spring.cloud.zookeeper.config.enabled=true"
);
}
@SpringBootApplication
static class Config {
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
@@ -29,12 +30,14 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
* @author Enrique Recarte Llorens * @author Enrique Recarte Llorens
*/ */
public class ZookeeperPropertySourceLocatorFailFastTests { public class ZookeeperPropertySourceLocatorFailFastTests {
@Rule @Rule
public ExpectedException expectedException = ExpectedException.none(); public ExpectedException expectedException = ExpectedException.none();
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// This system property makes Curator fail faster, otherwise it takes 15 seconds to trigger a retry // This system property makes Curator fail faster, otherwise it takes 15 seconds
// to trigger a retry
System.setProperty("curator-default-connection-timeout", "0"); System.setProperty("curator-default-connection-timeout", "0");
} }
@@ -45,39 +48,33 @@ public class ZookeeperPropertySourceLocatorFailFastTests {
@Test @Test
public void testFailFastFalseLoadsTheApplicationContext() throws Exception { public void testFailFastFalseLoadsTheApplicationContext() throws Exception {
new SpringApplicationBuilder() new SpringApplicationBuilder().sources(Config.class).web(WebApplicationType.NONE)
.sources(Config.class) .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast",
.web(WebApplicationType.NONE) "--spring.cloud.zookeeper.config.connectString=localhost:2188",
.run( "--spring.cloud.zookeeper.baseSleepTimeMs=0",
"--spring.application.name=testZookeeperPropertySourceLocatorFailFast", "--spring.cloud.zookeeper.maxRetries=0",
"--spring.cloud.zookeeper.config.connectString=localhost:2188", "--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.baseSleepTimeMs=0", "--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.maxRetries=0", "--spring.cloud.zookeeper.config.failFast=false");
"--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.config.failFast=false"
);
} }
@Test @Test
public void testFailFastTrueDoesNotLoadTheApplicationContext() throws Exception { public void testFailFastTrueDoesNotLoadTheApplicationContext() throws Exception {
expectedException.expect(Exception.class); expectedException.expect(Exception.class);
new SpringApplicationBuilder() new SpringApplicationBuilder().sources(Config.class).web(WebApplicationType.NONE)
.sources(Config.class) .run("--spring.application.name=testZookeeperPropertySourceLocatorFailFast",
.web(WebApplicationType.NONE) "--spring.cloud.zookeeper.config.connectString=localhost:2188",
.run( "--spring.cloud.zookeeper.baseSleepTimeMs=0",
"--spring.application.name=testZookeeperPropertySourceLocatorFailFast", "--spring.cloud.zookeeper.maxRetries=0",
"--spring.cloud.zookeeper.config.connectString=localhost:2188", "--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.baseSleepTimeMs=0", "--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.maxRetries=0", "--spring.cloud.zookeeper.config.failFast=true");
"--spring.cloud.zookeeper.maxSleepMs=0",
"--spring.cloud.zookeeper.blockUntilConnectedWait=0",
"--spring.cloud.zookeeper.config.failFast=true"
);
} }
@SpringBootApplication @SpringBootApplication
static class Config { static class Config {
} }
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,9 +19,7 @@ package org.springframework.cloud.zookeeper.config;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.GetChildrenBuilder; import org.apache.curator.framework.api.GetChildrenBuilder;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -36,7 +34,9 @@ public class ZookeeperPropertySourceLocatorNoApplicationNameTests {
public void defaultSpringApplicationNameWorks() { public void defaultSpringApplicationNameWorks() {
CuratorFramework curator = mock(CuratorFramework.class); CuratorFramework curator = mock(CuratorFramework.class);
when(curator.getChildren()).thenReturn(mock(GetChildrenBuilder.class)); when(curator.getChildren()).thenReturn(mock(GetChildrenBuilder.class));
ZookeeperPropertySourceLocator locator = new ZookeeperPropertySourceLocator(curator, new ZookeeperConfigProperties()); ZookeeperPropertySourceLocator locator = new ZookeeperPropertySourceLocator(
curator, new ZookeeperConfigProperties());
locator.locate(new MockEnvironment()); locator.locate(new MockEnvironment());
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -45,66 +45,54 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.SocketUtils; import org.springframework.util.SocketUtils;
import static org.hamcrest.Matchers.equalTo; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyString;
import static org.junit.Assert.assertThat;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class ZookeeperPropertySourceLocatorTests { public class ZookeeperPropertySourceLocatorTests {
private static final Log log = LogFactory.getLog(ZookeeperPropertySourceLocatorTests.class); private static final Log log = LogFactory
.getLog(ZookeeperPropertySourceLocatorTests.class);
public static final String PREFIX = "test__config__"; public static final String PREFIX = "test__config__";
public static final String ROOT = "/" + PREFIX + UUID.randomUUID(); public static final String ROOT = "/" + PREFIX + UUID.randomUUID();
public static final String CONTEXT = ROOT + "/application/"; public static final String CONTEXT = ROOT + "/application/";
public static final String KEY_BASIC = "testProp"; public static final String KEY_BASIC = "testProp";
public static final String KEY_BASIC_PATH = CONTEXT + KEY_BASIC; public static final String KEY_BASIC_PATH = CONTEXT + KEY_BASIC;
public static final String VAL_BASIC = "testPropVal"; public static final String VAL_BASIC = "testPropVal";
public static final String KEY_WITH_DOT = "testProp.dot"; public static final String KEY_WITH_DOT = "testProp.dot";
public static final String KEY_WITH_DOT_PATH = CONTEXT + KEY_WITH_DOT; public static final String KEY_WITH_DOT_PATH = CONTEXT + KEY_WITH_DOT;
public static final String VAL_WITH_DOT = "withDotVal"; public static final String VAL_WITH_DOT = "withDotVal";
public static final String KEY_NESTED = "testProp.nested"; public static final String KEY_NESTED = "testProp.nested";
public static final String KEY_NESTED_PATH = CONTEXT + KEY_NESTED.replace('.', '/'); public static final String KEY_NESTED_PATH = CONTEXT + KEY_NESTED.replace('.', '/');
public static final String VAL_NESTED = "nestedVal"; public static final String VAL_NESTED = "nestedVal";
public static final String KEY_WITHOUT_VALUE = "testProp.novalue"; public static final String KEY_WITHOUT_VALUE = "testProp.novalue";
public static final String KEY_WITHOUT_VALUE_PATH = CONTEXT + KEY_WITHOUT_VALUE; public static final String KEY_WITHOUT_VALUE_PATH = CONTEXT + KEY_WITHOUT_VALUE;
private ConfigurableEnvironment environment; private ConfigurableEnvironment environment;
private ConfigurableApplicationContext context; private ConfigurableApplicationContext context;
private TestingServer testingServer; private TestingServer testingServer;
private CuratorFramework curator; private CuratorFramework curator;
private ZookeeperConfigProperties properties; private ZookeeperConfigProperties properties;
@Configuration
@EnableAutoConfiguration
static class Config implements ApplicationListener<EnvironmentChangeEvent> {
@Bean
public CountDownLatch countDownLatch() {
return new CountDownLatch(1);
}
@Bean
public ContextRefresher contextRefresher(ConfigurableApplicationContext context,
RefreshScope scope) {
return new ContextRefresher(context, scope);
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
log.debug("Event keys: " + event.getKeys());
if (event.getKeys().contains(KEY_BASIC)) {
countDownLatch().countDown();
}
}
}
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
int port = SocketUtils.findAvailableTcpPort(); int port = SocketUtils.findAvailableTcpPort();
@@ -133,10 +121,12 @@ public class ZookeeperPropertySourceLocatorTests {
this.curator.close(); this.curator.close();
System.out.println(create); System.out.println(create);
this.context = new SpringApplicationBuilder(Config.class).web(WebApplicationType.NONE).run( this.context = new SpringApplicationBuilder(Config.class)
"--spring.cloud.zookeeper.connectString=" + connectString, .web(WebApplicationType.NONE)
"--spring.application.name=testZkPropertySource", "--logging.level.org.springframework.cloud.zookeeper=DEBUG", .run("--spring.cloud.zookeeper.connectString=" + connectString,
"--spring.cloud.zookeeper.config.root=" + ROOT); "--spring.application.name=testZkPropertySource",
"--logging.level.org.springframework.cloud.zookeeper=DEBUG",
"--spring.cloud.zookeeper.config.root=" + ROOT);
this.curator = this.context.getBean(CuratorFramework.class); this.curator = this.context.getBean(CuratorFramework.class);
this.properties = this.context.getBean(ZookeeperConfigProperties.class); this.properties = this.context.getBean(ZookeeperConfigProperties.class);
@@ -168,31 +158,57 @@ public class ZookeeperPropertySourceLocatorTests {
@Test @Test
public void checkKeyValues() throws Exception { public void checkKeyValues() throws Exception {
String propValue = this.environment.getProperty(KEY_BASIC); String propValue = this.environment.getProperty(KEY_BASIC);
assertThat(KEY_BASIC + " was wrong", propValue, is(equalTo(VAL_BASIC))); assertThat(propValue).as(KEY_BASIC + " was wrong").isEqualTo(VAL_BASIC);
propValue = this.environment.getProperty(KEY_NESTED); propValue = this.environment.getProperty(KEY_NESTED);
assertThat(VAL_NESTED + " was wrong", propValue, is(equalTo(VAL_NESTED))); assertThat(propValue).as(VAL_NESTED + " was wrong").isEqualTo(VAL_NESTED);
propValue = this.environment.getProperty(KEY_WITH_DOT); propValue = this.environment.getProperty(KEY_WITH_DOT);
assertThat(VAL_WITH_DOT + " was wrong", propValue, is(equalTo(VAL_WITH_DOT))); assertThat(propValue).as(VAL_WITH_DOT + " was wrong").isEqualTo(VAL_WITH_DOT);
propValue = this.environment.getProperty(KEY_WITHOUT_VALUE); propValue = this.environment.getProperty(KEY_WITHOUT_VALUE);
assertThat(KEY_WITHOUT_VALUE + " was wrong", propValue, is(isEmptyString())); assertThat(propValue).as(KEY_WITHOUT_VALUE + " was wrong").isEmpty();
} }
@Test @Test
public void propertyLoadedAndUpdated() throws Exception { public void propertyLoadedAndUpdated() throws Exception {
String testProp = this.environment.getProperty(KEY_BASIC); String testProp = this.environment.getProperty(KEY_BASIC);
assertThat("testProp was wrong", testProp, is(equalTo(VAL_BASIC))); assertThat(testProp).as("testProp was wrong").isEqualTo(VAL_BASIC);
this.curator.setData().forPath(KEY_BASIC_PATH, "testPropValUpdate".getBytes()); this.curator.setData().forPath(KEY_BASIC_PATH, "testPropValUpdate".getBytes());
CountDownLatch latch = this.context.getBean(CountDownLatch.class); CountDownLatch latch = this.context.getBean(CountDownLatch.class);
boolean receivedEvent = latch.await(15, TimeUnit.SECONDS); boolean receivedEvent = latch.await(15, TimeUnit.SECONDS);
assertThat("listener didn't receive event", receivedEvent, is(true)); assertThat(receivedEvent).as("listener didn't receive event").isTrue();
testProp = this.environment.getProperty(KEY_BASIC); testProp = this.environment.getProperty(KEY_BASIC);
assertThat("testProp was wrong after update", testProp, assertThat(testProp).as("testProp was wrong after update")
is(equalTo("testPropValUpdate"))); .isEqualTo("testPropValUpdate");
} }
@Configuration
@EnableAutoConfiguration
static class Config implements ApplicationListener<EnvironmentChangeEvent> {
@Bean
public CountDownLatch countDownLatch() {
return new CountDownLatch(1);
}
@Bean
public ContextRefresher contextRefresher(ConfigurableApplicationContext context,
RefreshScope scope) {
return new ContextRefresher(context, scope);
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
log.debug("Event keys: " + event.getKeys());
if (event.getKeys().contains(KEY_BASIC)) {
countDownLatch().countDown();
}
}
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,12 +24,14 @@ import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/** /**
* Wrapper annotation to enable Zookeeper * Wrapper annotation to enable Zookeeper.
* *
* @author Marcin Grzejszczak
* @since 1.1.0 * @since 1.1.0
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "spring.cloud.zookeeper.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.enabled", matchIfMissing = true)
public @interface ConditionalOnZookeeperEnabled { public @interface ConditionalOnZookeeperEnabled {
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import org.apache.curator.ensemble.EnsembleProvider;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -30,8 +31,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* that sets up Zookeeper discovery. * Auto-configuration} that sets up Zookeeper discovery.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -52,20 +53,24 @@ public class ZookeeperAutoConfiguration {
return new ZookeeperProperties(); return new ZookeeperProperties();
} }
@Bean(destroyMethod = "close") @Bean(destroyMethod = "close")
@ConditionalOnMissingBean @ConditionalOnMissingBean
public CuratorFramework curatorFramework(RetryPolicy retryPolicy, ZookeeperProperties properties) throws Exception { public CuratorFramework curatorFramework(RetryPolicy retryPolicy,
ZookeeperProperties properties) throws Exception {
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder(); CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
if (this.ensembleProvider != null) { if (this.ensembleProvider != null) {
builder.ensembleProvider(this.ensembleProvider); builder.ensembleProvider(this.ensembleProvider);
} else { }
else {
builder.connectString(properties.getConnectString()); builder.connectString(properties.getConnectString());
} }
CuratorFramework curator = builder.retryPolicy(retryPolicy).build(); CuratorFramework curator = builder.retryPolicy(retryPolicy).build();
curator.start(); curator.start();
log.trace("blocking until connected to zookeeper for " + properties.getBlockUntilConnectedWait() + properties.getBlockUntilConnectedUnit()); log.trace("blocking until connected to zookeeper for "
curator.blockUntilConnected(properties.getBlockUntilConnectedWait(), properties.getBlockUntilConnectedUnit()); + properties.getBlockUntilConnectedWait()
+ properties.getBlockUntilConnectedUnit());
curator.blockUntilConnected(properties.getBlockUntilConnectedWait(),
properties.getBlockUntilConnectedUnit());
log.trace("connected to zookeeper"); log.trace("connected to zookeeper");
return curator; return curator;
} }
@@ -74,7 +79,7 @@ public class ZookeeperAutoConfiguration {
@ConditionalOnMissingBean @ConditionalOnMissingBean
public RetryPolicy exponentialBackoffRetry(ZookeeperProperties properties) { public RetryPolicy exponentialBackoffRetry(ZookeeperProperties properties) {
return new ExponentialBackoffRetry(properties.getBaseSleepTimeMs(), return new ExponentialBackoffRetry(properties.getBaseSleepTimeMs(),
properties.getMaxRetries(), properties.getMaxRetries(), properties.getMaxSleepMs());
properties.getMaxSleepMs());
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2018 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper; package org.springframework.cloud.zookeeper;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -28,8 +30,8 @@ import org.springframework.context.annotation.Configuration;
/** /**
* Auto {@link Configuration} for adding a Zookeeper health endpoint to actuator if * Auto {@link Configuration} for adding a Zookeeper health endpoint to actuator if
* required. * required.
* *
* @author tgianos * @author Tom Gianos
* @since 2.0.1 * @since 2.0.1
*/ */
@Configuration @Configuration
@@ -41,7 +43,6 @@ public class ZookeeperHealthAutoConfiguration {
/** /**
* If there is an active curator, if the zookeeper health endpoint is enabled and if a * If there is an active curator, if the zookeeper health endpoint is enabled and if a
* health indicator hasn't already been added by a user add one. * health indicator hasn't already been added by a user add one.
*
* @param curator The curator connection to zookeeper to use * @param curator The curator connection to zookeeper to use
* @return An instance of {@link ZookeeperHealthIndicator} to add to actuator health * @return An instance of {@link ZookeeperHealthIndicator} to add to actuator health
* report * report
@@ -53,4 +54,5 @@ public class ZookeeperHealthAutoConfiguration {
public ZookeeperHealthIndicator zookeeperHealthIndicator(CuratorFramework curator) { public ZookeeperHealthIndicator zookeeperHealthIndicator(CuratorFramework curator) {
return new ZookeeperHealthIndicator(curator); return new ZookeeperHealthIndicator(curator);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.cloud.zookeeper;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.imps.CuratorFrameworkState; import org.apache.curator.framework.imps.CuratorFrameworkState;
import org.springframework.boot.actuate.health.AbstractHealthIndicator; import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.Health;
@@ -29,6 +30,7 @@ import org.springframework.boot.actuate.health.Health;
* @since 1.0.0 * @since 1.0.0
*/ */
public class ZookeeperHealthIndicator extends AbstractHealthIndicator { public class ZookeeperHealthIndicator extends AbstractHealthIndicator {
private final CuratorFramework curator; private final CuratorFramework curator;
public ZookeeperHealthIndicator(CuratorFramework curator) { public ZookeeperHealthIndicator(CuratorFramework curator) {
@@ -56,4 +58,5 @@ public class ZookeeperHealthIndicator extends AbstractHealthIndicator {
builder.down(e); builder.down(e);
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,14 +16,15 @@
package org.springframework.cloud.zookeeper; package org.springframework.cloud.zookeeper;
import javax.validation.constraints.NotNull;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
/** /**
* Properties related to connecting to Zookeeper * Properties related to connecting to Zookeeper.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -33,38 +34,38 @@ import org.springframework.validation.annotation.Validated;
public class ZookeeperProperties { public class ZookeeperProperties {
/** /**
* Connection string to the Zookeeper cluster * Connection string to the Zookeeper cluster.
*/ */
@NotNull @NotNull
private String connectString = "localhost:2181"; private String connectString = "localhost:2181";
/** /**
* Is Zookeeper enabled * Is Zookeeper enabled.
*/ */
private boolean enabled = true; private boolean enabled = true;
/** /**
* Initial amount of time to wait between retries * Initial amount of time to wait between retries.
*/ */
private Integer baseSleepTimeMs = 50; private Integer baseSleepTimeMs = 50;
/** /**
* Max number of times to retry * Max number of times to retry.
*/ */
private Integer maxRetries = 10; private Integer maxRetries = 10;
/** /**
* Max time in ms to sleep on each retry * Max time in ms to sleep on each retry.
*/ */
private Integer maxSleepMs = 500; private Integer maxSleepMs = 500;
/** /**
* Wait time to block on connection to Zookeeper * Wait time to block on connection to Zookeeper.
*/ */
private Integer blockUntilConnectedWait = 10; private Integer blockUntilConnectedWait = 10;
/** /**
* The unit of time related to blocking on connection to Zookeeper * The unit of time related to blocking on connection to Zookeeper.
*/ */
private TimeUnit blockUntilConnectedUnit = TimeUnit.SECONDS; private TimeUnit blockUntilConnectedUnit = TimeUnit.SECONDS;
@@ -123,4 +124,5 @@ public class ZookeeperProperties {
public void setBlockUntilConnectedUnit(TimeUnit blockUntilConnectedUnit) { public void setBlockUntilConnectedUnit(TimeUnit blockUntilConnectedUnit) {
this.blockUntilConnectedUnit = blockUntilConnectedUnit; this.blockUntilConnectedUnit = blockUntilConnectedUnit;
} }
} }

View File

@@ -1,7 +1,20 @@
package org.springframework.cloud.zookeeper; /*
* Copyright 2015-2019 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.
*/
import static org.junit.Assert.assertEquals; package org.springframework.cloud.zookeeper;
import static org.junit.Assert.assertNotEquals;
import org.apache.curator.ensemble.EnsembleProvider; import org.apache.curator.ensemble.EnsembleProvider;
import org.apache.curator.ensemble.fixed.FixedEnsembleProvider; import org.apache.curator.ensemble.fixed.FixedEnsembleProvider;
@@ -9,26 +22,35 @@ import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author Konrad Kamil Dobrzyński * @author Konrad Kamil Dobrzyński
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ZookeeperAutoConfigurationEnsembleTests.TestConfig.class, ZookeeperAutoConfiguration.class }) @ContextConfiguration(classes = {
ZookeeperAutoConfigurationEnsembleTests.TestConfig.class,
ZookeeperAutoConfiguration.class })
public class ZookeeperAutoConfigurationEnsembleTests { public class ZookeeperAutoConfigurationEnsembleTests {
@Autowired(required = false) CuratorFramework curator; @Autowired(required = false)
CuratorFramework curator;
@Autowired
TestingServer testingServer;
@Autowired TestingServer testingServer;
@Test @Test
public void should_successfully_inject_Curator_with_ensemble_connection_string() { public void should_successfully_inject_Curator_with_ensemble_connection_string() {
assertEquals(testingServer.getConnectString(), curator.getZookeeperClient().getCurrentConnectionString()); assertThat(curator.getZookeeperClient().getCurrentConnectionString())
assertNotEquals(TestConfig.DUMMY_CONNECTION_STRING, curator.getZookeeperClient().getCurrentConnectionString()); .isEqualTo(testingServer.getConnectString());
assertThat(curator.getZookeeperClient().getCurrentConnectionString())
.isNotEqualTo(TestConfig.DUMMY_CONNECTION_STRING);
} }
static class TestConfig { static class TestConfig {
@@ -36,7 +58,7 @@ public class ZookeeperAutoConfigurationEnsembleTests {
static final String DUMMY_CONNECTION_STRING = "dummy-connection-string:2111"; static final String DUMMY_CONNECTION_STRING = "dummy-connection-string:2111";
@Bean @Bean
EnsembleProvider ensembleProvider(TestingServer testingServer){ EnsembleProvider ensembleProvider(TestingServer testingServer) {
return new FixedEnsembleProvider(testingServer.getConnectString()); return new FixedEnsembleProvider(testingServer.getConnectString());
} }
@@ -47,8 +69,11 @@ public class ZookeeperAutoConfigurationEnsembleTests {
return properties; return properties;
} }
@Bean(destroyMethod = "close") TestingServer testingServer() throws Exception { @Bean(destroyMethod = "close")
TestingServer testingServer() throws Exception {
return new TestingServer(); return new TestingServer();
} }
} }
} }

View File

@@ -1,40 +1,64 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertNotNull; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ZookeeperAutoConfigurationTests.TestConfig.class, ZookeeperAutoConfiguration.class }) @ContextConfiguration(classes = { ZookeeperAutoConfigurationTests.TestConfig.class,
ZookeeperAutoConfiguration.class })
public class ZookeeperAutoConfigurationTests { public class ZookeeperAutoConfigurationTests {
@Autowired(required = false) CuratorFramework curator; @Autowired(required = false)
CuratorFramework curator;
@Test @Test
public void should_successfully_inject_Curator_as_a_Spring_bean() { public void should_successfully_inject_Curator_as_a_Spring_bean() {
assertNotNull(this.curator); assertThat(this.curator).isNotNull();
} }
static class TestConfig { static class TestConfig {
@Bean @Bean
ZookeeperProperties zookeeperProperties(TestingServer testingServer) throws Exception { ZookeeperProperties zookeeperProperties(TestingServer testingServer)
throws Exception {
ZookeeperProperties properties = new ZookeeperProperties(); ZookeeperProperties properties = new ZookeeperProperties();
properties.setConnectString(testingServer.getConnectString()); properties.setConnectString(testingServer.getConnectString());
return properties; return properties;
} }
@Bean(destroyMethod = "close") TestingServer testingServer() throws Exception { @Bean(destroyMethod = "close")
TestingServer testingServer() throws Exception {
return new TestingServer(); return new TestingServer();
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2018 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,22 +13,25 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper; package org.springframework.cloud.zookeeper;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
/** /**
* Tests for {@link ZookeeperHealthAutoConfiguration}. * Tests for {@link ZookeeperHealthAutoConfiguration}.
* *
* @author tgianos * @author Tom Gianos
* @since 2.0.1 * @since 2.0.1
*/ */
public class ZookeeperHealthAutoConfigurationTests { public class ZookeeperHealthAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ZookeeperAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(ZookeeperAutoConfiguration.class,
ZookeeperHealthAutoConfiguration.class)) ZookeeperHealthAutoConfiguration.class))
@@ -61,10 +64,13 @@ public class ZookeeperHealthAutoConfigurationTests {
} }
static class HealthIndicatorCustomConfig { static class HealthIndicatorCustomConfig {
@Bean @Bean
ZookeeperHealthIndicator customZookeeperHealthIndicator( ZookeeperHealthIndicator customZookeeperHealthIndicator(
CuratorFramework curatorFramework) { CuratorFramework curatorFramework) {
return new ZookeeperHealthIndicator(curatorFramework); return new ZookeeperHealthIndicator(curatorFramework);
} }
} }
} }

View File

@@ -15,6 +15,9 @@
<description>Spring Cloud Zookeeper Dependencies</description> <description>Spring Cloud Zookeeper Dependencies</description>
<properties> <properties>
<curator.version>4.0.1</curator.version> <curator.version>4.0.1</curator.version>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failsOnViolation>true</maven-checkstyle-plugin.failsOnViolation>
<maven-checkstyle-plugin.includeTestSourceDirectory>true</maven-checkstyle-plugin.includeTestSourceDirectory>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
@@ -116,6 +119,27 @@
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</reporting>
<profiles> <profiles>
<profile> <profile>
<id>spring</id> <id>spring</id>

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,12 +24,14 @@ import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/** /**
* Wrapper annotation to enable Ribbon for Zookeeper * Wrapper annotation to enable Ribbon for Zookeeper.
* *
* @since 1.0.0 * @author Marcin Grzejszczak
* * @since 1.0.0
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(value = "ribbon.zookeeper.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "ribbon.zookeeper.enabled", matchIfMissing = true)
public @interface ConditionalOnRibbonZookeeper { public @interface ConditionalOnRibbonZookeeper {
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -25,13 +25,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled;
/** /**
* Wrapper annotation to enable Zookeeper Discovery * Wrapper annotation to enable Zookeeper Discovery.
* *
* @author Marcin Grzejszczak
* @since 1.1.0 * @since 1.1.0
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnZookeeperEnabled @ConditionalOnZookeeperEnabled
@ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true)
public @interface ConditionalOnZookeeperDiscoveryEnabled { public @interface ConditionalOnZookeeperDiscoveryEnabled {
} }

View File

@@ -1,17 +1,37 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
/** /**
* Utils for correct dependency path format * Utils for correct dependency path format.
* *
* @author Denis Stepanov * @author Denis Stepanov
* @since 1.0.4 * @since 1.0.4
*/ */
public class DependencyPathUtils { public final class DependencyPathUtils {
private DependencyPathUtils() {
}
/** /**
* Sanitizes path by ensuring that path starts with a slash and doesn't have one at the end * Sanitizes path by ensuring that path starts with a slash and doesn't have one at
* @param path * the end.
* @return * @param path file path to sanitize.
* @return sanitized path.
*/ */
public static String sanitize(String path) { public static String sanitize(String path) {
return withLeadingSlash(withoutSlashAtEnd(path)); return withLeadingSlash(withoutSlashAtEnd(path));

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -26,8 +26,8 @@ import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* that sets up Ribbon for Zookeeper. * Auto-configuration} that sets up Ribbon for Zookeeper.
* *
* @author Dave Syer * @author Dave Syer
* @since 1.0.0 * @since 1.0.0
@@ -40,4 +40,5 @@ import org.springframework.context.annotation.Configuration;
@AutoConfigureAfter(RibbonAutoConfiguration.class) @AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = ZookeeperRibbonClientConfiguration.class) @RibbonClients(defaultConfiguration = ZookeeperRibbonClientConfiguration.class)
public class RibbonZookeeperAutoConfiguration { public class RibbonZookeeperAutoConfiguration {
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.cloud.zookeeper.discovery;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
@@ -40,8 +41,9 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@ConditionalOnBean(ZookeeperDiscoveryClientConfiguration.Marker.class) @ConditionalOnBean(ZookeeperDiscoveryClientConfiguration.Marker.class)
@ConditionalOnZookeeperDiscoveryEnabled @ConditionalOnZookeeperDiscoveryEnabled
@AutoConfigureBefore({CommonsClientAutoConfiguration.class, NoopDiscoveryClientAutoConfiguration.class}) @AutoConfigureBefore({ CommonsClientAutoConfiguration.class,
@AutoConfigureAfter({ZookeeperDiscoveryClientConfiguration.class}) NoopDiscoveryClientAutoConfiguration.class })
@AutoConfigureAfter({ ZookeeperDiscoveryClientConfiguration.class })
public class ZookeeperDiscoveryAutoConfiguration { public class ZookeeperDiscoveryAutoConfiguration {
@Autowired(required = false) @Autowired(required = false)
@@ -52,13 +54,15 @@ public class ZookeeperDiscoveryAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) { public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(
InetUtils inetUtils) {
return new ZookeeperDiscoveryProperties(inetUtils); return new ZookeeperDiscoveryProperties(inetUtils);
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
// currently means auto-registration is false. That will change when ZookeeperServiceDiscovery is gone // currently means auto-registration is false. That will change when
// ZookeeperServiceDiscovery is gone
public ZookeeperDiscoveryClient zookeeperDiscoveryClient( public ZookeeperDiscoveryClient zookeeperDiscoveryClient(
ServiceDiscovery<ZookeeperInstance> serviceDiscovery, ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) { ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
@@ -66,10 +70,17 @@ public class ZookeeperDiscoveryAutoConfiguration {
zookeeperDiscoveryProperties); zookeeperDiscoveryProperties);
} }
@Bean
public ZookeeperServiceWatch zookeeperServiceWatch(
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
return new ZookeeperServiceWatch(this.curator, zookeeperDiscoveryProperties);
}
@Configuration @Configuration
@ConditionalOnEnabledHealthIndicator("zookeeper") @ConditionalOnEnabledHealthIndicator("zookeeper")
@ConditionalOnClass(Endpoint.class) @ConditionalOnClass(Endpoint.class)
protected static class ZookeeperDiscoveryHealthConfig { protected static class ZookeeperDiscoveryHealthConfig {
@Autowired(required = false) @Autowired(required = false)
private ZookeeperDependencies zookeeperDependencies; private ZookeeperDependencies zookeeperDependencies;
@@ -82,11 +93,7 @@ public class ZookeeperDiscoveryAutoConfiguration {
return new ZookeeperDiscoveryHealthIndicator(curatorFramework, return new ZookeeperDiscoveryHealthIndicator(curatorFramework,
serviceDiscovery, this.zookeeperDependencies, properties); serviceDiscovery, this.zookeeperDependencies, properties);
} }
}
@Bean
public ZookeeperServiceWatch zookeeperServiceWatch(ZookeeperDiscoveryProperties zookeeperDiscoveryProperties) {
return new ZookeeperServiceWatch(this.curator, zookeeperDiscoveryProperties);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -46,7 +46,9 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
private static final Log log = LogFactory.getLog(ZookeeperDiscoveryClient.class); private static final Log log = LogFactory.getLog(ZookeeperDiscoveryClient.class);
private final ZookeeperDependencies zookeeperDependencies; private final ZookeeperDependencies zookeeperDependencies;
private final ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private final ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
public ZookeeperDiscoveryClient(ServiceDiscovery<ZookeeperInstance> serviceDiscovery, public ZookeeperDiscoveryClient(ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
@@ -62,7 +64,8 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
return "Spring Cloud Zookeeper Discovery Client"; return "Spring Cloud Zookeeper Discovery Client";
} }
private static org.springframework.cloud.client.ServiceInstance createServiceInstance(String serviceId, ServiceInstance<ZookeeperInstance> serviceInstance) { private static org.springframework.cloud.client.ServiceInstance createServiceInstance(
String serviceId, ServiceInstance<ZookeeperInstance> serviceInstance) {
return new ZookeeperServiceInstance(serviceId, serviceInstance); return new ZookeeperServiceInstance(serviceId, serviceInstance);
} }
@@ -74,19 +77,24 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
String serviceIdToQuery = getServiceIdToQuery(serviceId); String serviceIdToQuery = getServiceIdToQuery(serviceId);
Collection<ServiceInstance<ZookeeperInstance>> zkInstances = getServiceDiscovery().queryForInstances(serviceIdToQuery); Collection<ServiceInstance<ZookeeperInstance>> zkInstances = getServiceDiscovery()
.queryForInstances(serviceIdToQuery);
List<org.springframework.cloud.client.ServiceInstance> instances = new ArrayList<>(); List<org.springframework.cloud.client.ServiceInstance> instances = new ArrayList<>();
for (ServiceInstance<ZookeeperInstance> instance : zkInstances) { for (ServiceInstance<ZookeeperInstance> instance : zkInstances) {
instances.add(createServiceInstance(serviceIdToQuery, instance)); instances.add(createServiceInstance(serviceIdToQuery, instance));
} }
return instances; return instances;
} catch (KeeperException.NoNodeException e) { }
catch (KeeperException.NoNodeException e) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Error getting instances from zookeeper. Possibly, no service has registered.", e); log.debug(
"Error getting instances from zookeeper. Possibly, no service has registered.",
e);
} }
// this means that nothing has registered as a service yes // this means that nothing has registered as a service yes
return Collections.emptyList(); return Collections.emptyList();
} catch (Exception exception) { }
catch (Exception exception) {
rethrowRuntimeException(exception); rethrowRuntimeException(exception);
} }
return new ArrayList<>(); return new ArrayList<>();
@@ -97,7 +105,8 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
} }
private String getServiceIdToQuery(String serviceId) { private String getServiceIdToQuery(String serviceId) {
if (this.zookeeperDependencies != null && this.zookeeperDependencies.hasDependencies()) { if (this.zookeeperDependencies != null
&& this.zookeeperDependencies.hasDependencies()) {
String pathForAlias = this.zookeeperDependencies.getPathForAlias(serviceId); String pathForAlias = this.zookeeperDependencies.getPathForAlias(serviceId);
return pathForAlias.isEmpty() ? serviceId : pathForAlias; return pathForAlias.isEmpty() ? serviceId : pathForAlias;
} }
@@ -108,7 +117,8 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
public List<String> getServices() { public List<String> getServices() {
List<String> services = null; List<String> services = null;
if (getServiceDiscovery() == null) { if (getServiceDiscovery() == null) {
log.warn("Service Discovery is not yet ready - returning empty list of services"); log.warn(
"Service Discovery is not yet ready - returning empty list of services");
return Collections.emptyList(); return Collections.emptyList();
} }
try { try {
@@ -120,7 +130,9 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
} }
catch (KeeperException.NoNodeException e) { catch (KeeperException.NoNodeException e) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Error getting services from zookeeper. Possibly, no service has registered.", e); log.debug(
"Error getting services from zookeeper. Possibly, no service has registered.",
e);
} }
// this means that nothing has registered as a service yes // this means that nothing has registered as a service yes
return Collections.emptyList(); return Collections.emptyList();
@@ -135,4 +147,5 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
public int getOrder() { public int getOrder() {
return this.zookeeperDiscoveryProperties.getOrder(); return this.zookeeperDiscoveryProperties.getOrder();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* {@link org.springframework.cloud.client.discovery.DiscoveryClient} configuration * {@link org.springframework.cloud.client.discovery.DiscoveryClient} configuration for
* for Zookeeper. * Zookeeper.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -31,11 +31,12 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.discovery.enabled", matchIfMissing = true)
public class ZookeeperDiscoveryClientConfiguration { public class ZookeeperDiscoveryClientConfiguration {
class Marker {}
@Bean @Bean
public Marker zookeeperDiscoveryClientMarker() { public Marker zookeeperDiscoveryClientMarker() {
return new Marker(); return new Marker();
} }
class Marker {
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.Health;
import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator; import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
@@ -38,8 +39,11 @@ public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicat
.getLog(ZookeeperDiscoveryHealthIndicator.class); .getLog(ZookeeperDiscoveryHealthIndicator.class);
private CuratorFramework curatorFramework; private CuratorFramework curatorFramework;
private ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
private final ZookeeperDependencies zookeeperDependencies; private final ZookeeperDependencies zookeeperDependencies;
private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
public ZookeeperDiscoveryHealthIndicator(CuratorFramework curatorFramework, public ZookeeperDiscoveryHealthIndicator(CuratorFramework curatorFramework,
@@ -61,10 +65,9 @@ public class ZookeeperDiscoveryHealthIndicator implements DiscoveryHealthIndicat
public Health health() { public Health health() {
Health.Builder builder = Health.unknown(); Health.Builder builder = Health.unknown();
try { try {
Iterable<ServiceInstance<ZookeeperInstance>> allInstances = Iterable<ServiceInstance<ZookeeperInstance>> allInstances = new ZookeeperServiceInstances(
new ZookeeperServiceInstances(this.curatorFramework, this.curatorFramework, this.serviceDiscovery,
this.serviceDiscovery, this.zookeeperDependencies, this.zookeeperDependencies, this.zookeeperDiscoveryProperties);
this.zookeeperDiscoveryProperties);
builder.up().withDetail("services", allInstances); builder.up().withDetail("services", allInstances);
} }
catch (Exception e) { catch (Exception e) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -33,6 +33,9 @@ import org.springframework.util.StringUtils;
@ConfigurationProperties("spring.cloud.zookeeper.discovery") @ConfigurationProperties("spring.cloud.zookeeper.discovery")
public class ZookeeperDiscoveryProperties { public class ZookeeperDiscoveryProperties {
/**
* Default URI spec.
*/
public static final String DEFAULT_URI_SPEC = "{scheme}://{address}:{port}"; public static final String DEFAULT_URI_SPEC = "{scheme}://{address}:{port}";
private InetUtils.HostInfo hostInfo; private InetUtils.HostInfo hostInfo;
@@ -40,12 +43,12 @@ public class ZookeeperDiscoveryProperties {
private boolean enabled = true; private boolean enabled = true;
/** /**
* Root Zookeeper folder in which all instances are registered * Root Zookeeper folder in which all instances are registered.
*/ */
private String root = "/services"; private String root = "/services";
/** /**
* The URI specification to resolve during service registration in Zookeeper * The URI specification to resolve during service registration in Zookeeper.
*/ */
private String uriSpec = DEFAULT_URI_SPEC; private String uriSpec = DEFAULT_URI_SPEC;
@@ -58,16 +61,17 @@ public class ZookeeperDiscoveryProperties {
*/ */
private String instanceHost; private String instanceHost;
/** IP address to use when accessing service (must also set preferIpAddress /**
to use) */ * IP address to use when accessing service (must also set preferIpAddress to use).
*/
private String instanceIpAddress; private String instanceIpAddress;
/** /**
* Use ip address rather than hostname during registration * Use ip address rather than hostname during registration.
*/ */
private boolean preferIpAddress = false; private boolean preferIpAddress = false;
/** Port to register the service under (defaults to listening port) */ /** Port to register the service under (defaults to listening port). */
private Integer instancePort; private Integer instancePort;
/** Ssl port of the registered service. */ /** Ssl port of the registered service. */
@@ -85,17 +89,20 @@ public class ZookeeperDiscoveryProperties {
private Map<String, String> metadata = new HashMap<>(); private Map<String, String> metadata = new HashMap<>();
/** /**
* The initial status of this instance (defaults to {@link StatusConstants#STATUS_UP}). * The initial status of this instance (defaults to
* {@link StatusConstants#STATUS_UP}).
*/ */
private String initialStatus = StatusConstants.STATUS_UP; private String initialStatus = StatusConstants.STATUS_UP;
/** /**
* Order of the discovery client used by `CompositeDiscoveryClient` for sorting available clients. * Order of the discovery client used by `CompositeDiscoveryClient` for sorting
* available clients.
*/ */
private int order = 0; private int order = 0;
// Visible for Testing // Visible for Testing
protected ZookeeperDiscoveryProperties() {} protected ZookeeperDiscoveryProperties() {
}
public ZookeeperDiscoveryProperties(InetUtils inetUtils) { public ZookeeperDiscoveryProperties(InetUtils inetUtils) {
this.hostInfo = inetUtils.findFirstNonLoopbackHostInfo(); this.hostInfo = inetUtils.findFirstNonLoopbackHostInfo();
@@ -206,17 +213,13 @@ public class ZookeeperDiscoveryProperties {
@Override @Override
public String toString() { public String toString() {
return "ZookeeperDiscoveryProperties{" + "enabled=" + this.enabled + return "ZookeeperDiscoveryProperties{" + "enabled=" + this.enabled + ", root='"
", root='" + this.root + '\'' + + this.root + '\'' + ", uriSpec='" + this.uriSpec + '\''
", uriSpec='" + this.uriSpec + '\'' + + ", instanceId='" + this.instanceId + '\'' + ", instanceHost='"
", instanceId='" + this.instanceId + '\'' + + this.instanceHost + '\'' + ", instancePort='" + this.instancePort + '\''
", instanceHost='" + this.instanceHost + '\'' + + ", instanceSslPort='" + this.instanceSslPort + '\'' + ", metadata="
", instancePort='" + this.instancePort + '\'' + + this.metadata + ", register=" + this.register + ", initialStatus="
", instanceSslPort='" + this.instanceSslPort + '\'' + + this.initialStatus + ", order=" + this.order + '}';
", metadata=" + this.metadata +
", register=" + this.register +
", initialStatus=" + this.initialStatus +
", order=" + this.order +
'}';
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -26,8 +26,11 @@ import java.util.Map;
* @since 1.0.0 * @since 1.0.0
*/ */
public class ZookeeperInstance { public class ZookeeperInstance {
private String id; private String id;
private String name; private String name;
private Map<String, String> metadata = new HashMap<>(); private Map<String, String> metadata = new HashMap<>();
@SuppressWarnings("unused") @SuppressWarnings("unused")
@@ -66,9 +69,8 @@ public class ZookeeperInstance {
@Override @Override
public String toString() { public String toString() {
return "ZookeeperInstance{" + "id='" + this.id + '\'' + return "ZookeeperInstance{" + "id='" + this.id + '\'' + ", name='" + this.name
", name='" + this.name + '\'' + + '\'' + ", metadata=" + this.metadata + '}';
", metadata=" + this.metadata +
'}';
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,9 +18,18 @@ package org.springframework.cloud.zookeeper.discovery;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
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.ILoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.PingUrl;
import com.netflix.loadbalancer.ServerList;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -32,15 +41,6 @@ import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDepende
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.ILoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.PingUrl;
import com.netflix.loadbalancer.ServerList;
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses; import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity; import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
@@ -56,9 +56,12 @@ import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity
*/ */
@Configuration @Configuration
public class ZookeeperRibbonClientConfiguration { public class ZookeeperRibbonClientConfiguration {
private static final Log log = LogFactory.getLog(ZookeeperRibbonClientConfiguration.class);
private static final Log log = LogFactory
.getLog(ZookeeperRibbonClientConfiguration.class);
protected static final String VALUE_NOT_SET = "__not__set__"; protected static final String VALUE_NOT_SET = "__not__set__";
protected static final String DEFAULT_NAMESPACE = "ribbon"; protected static final String DEFAULT_NAMESPACE = "ribbon";
@Value("${ribbon.client.name}") @Value("${ribbon.client.name}")
@@ -75,7 +78,9 @@ public class ZookeeperRibbonClientConfiguration {
ServiceDiscovery<ZookeeperInstance> serviceDiscovery) { ServiceDiscovery<ZookeeperInstance> serviceDiscovery) {
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery); ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
serverList.initFromDependencies(config, zookeeperDependencies); serverList.initFromDependencies(config, zookeeperDependencies);
log.debug(String.format("Server list for Ribbon's dependencies based load balancing is [%s]", serverList)); log.debug(String.format(
"Server list for Ribbon's dependencies based load balancing is [%s]",
serverList));
return serverList; return serverList;
} }
@@ -83,9 +88,11 @@ public class ZookeeperRibbonClientConfiguration {
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnDependenciesPassed @ConditionalOnDependenciesPassed
@ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.ribbon.loadbalancer", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.ribbon.loadbalancer", matchIfMissing = true)
public ILoadBalancer dependenciesBasedLoadBalancer(ZookeeperDependencies zookeeperDependencies, public ILoadBalancer dependenciesBasedLoadBalancer(
ServerList<?> serverList, IClientConfig config, IPing iPing) { ZookeeperDependencies zookeeperDependencies, ServerList<?> serverList,
return new DependenciesBasedLoadBalancer(zookeeperDependencies, serverList, config, iPing); IClientConfig config, IPing iPing) {
return new DependenciesBasedLoadBalancer(zookeeperDependencies, serverList,
config, iPing);
} }
@Bean @Bean
@@ -102,11 +109,12 @@ public class ZookeeperRibbonClientConfiguration {
ServiceDiscovery<ZookeeperInstance> serviceDiscovery) { ServiceDiscovery<ZookeeperInstance> serviceDiscovery) {
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery); ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
serverList.initWithNiwsConfig(config); serverList.initWithNiwsConfig(config);
log.debug(String.format("Server list for Ribbon's non-dependency based load balancing is [%s]", serverList)); log.debug(String.format(
"Server list for Ribbon's non-dependency based load balancing is [%s]",
serverList));
return serverList; return serverList;
} }
@Bean @Bean
public ServerIntrospector serverIntrospector() { public ServerIntrospector serverIntrospector() {
return new ZookeeperServerIntrospector(); return new ZookeeperServerIntrospector();

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,12 +16,11 @@
package org.springframework.cloud.zookeeper.discovery; package org.springframework.cloud.zookeeper.discovery;
import com.netflix.loadbalancer.Server;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import com.netflix.loadbalancer.Server;
/** /**
* A Zookeeper version of a {@link Server Ribbon Server} * A Zookeeper version of a {@link Server Ribbon Server}.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -29,6 +28,7 @@ import com.netflix.loadbalancer.Server;
public class ZookeeperServer extends Server { public class ZookeeperServer extends Server {
private final MetaInfo metaInfo; private final MetaInfo metaInfo;
private ServiceInstance<ZookeeperInstance> instance; private ServiceInstance<ZookeeperInstance> instance;
public ZookeeperServer(final ServiceInstance<ZookeeperInstance> instance) { public ZookeeperServer(final ServiceInstance<ZookeeperInstance> instance) {
@@ -66,4 +66,5 @@ public class ZookeeperServer extends Server {
public ServiceInstance<ZookeeperInstance> getInstance() { public ServiceInstance<ZookeeperInstance> getInstance() {
return this.instance; return this.instance;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,16 +16,18 @@
package org.springframework.cloud.zookeeper.discovery; package org.springframework.cloud.zookeeper.discovery;
import java.util.Map;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import java.util.Map; import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class ZookeeperServerIntrospector extends DefaultServerIntrospector { public class ZookeeperServerIntrospector extends DefaultServerIntrospector {
@Override @Override
public boolean isSecure(Server server) { public boolean isSecure(Server server) {
if (server instanceof ZookeeperServer) { if (server instanceof ZookeeperServer) {
@@ -47,4 +49,5 @@ public class ZookeeperServerIntrospector extends DefaultServerIntrospector {
} }
return super.getMetadata(server); return super.getMetadata(server);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,22 +21,22 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.util.StringUtils;
import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList; 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 org.springframework.util.StringUtils;
import static org.springframework.cloud.zookeeper.support.StatusConstants.INSTANCE_STATUS_KEY; import static org.springframework.cloud.zookeeper.support.StatusConstants.INSTANCE_STATUS_KEY;
import static org.springframework.cloud.zookeeper.support.StatusConstants.STATUS_UP; import static org.springframework.cloud.zookeeper.support.StatusConstants.STATUS_UP;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException; import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/** /**
* Zookeeper version of {@link AbstractServerList} that returns the list of * Zookeeper version of {@link AbstractServerList} that returns the list of servers on
* servers on which instances are ran. The implementation is capable of resolving * which instances are ran. The implementation is capable of resolving the servers from
* the servers from {@link ZookeeperDependencies}. * {@link ZookeeperDependencies}.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
@@ -45,6 +45,7 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> { public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
private String serviceId; private String serviceId;
private final ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private final ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
public ZookeeperServerList(ServiceDiscovery<ZookeeperInstance> serviceDiscovery) { public ZookeeperServerList(ServiceDiscovery<ZookeeperInstance> serviceDiscovery) {
@@ -56,13 +57,18 @@ public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
this.serviceId = clientConfig.getClientName(); this.serviceId = clientConfig.getClientName();
} }
public void initFromDependencies(IClientConfig clientConfig, ZookeeperDependencies zookeeperDependencies) { public void initFromDependencies(IClientConfig clientConfig,
this.serviceId = getServiceIdFromDepsOrClientName(clientConfig, zookeeperDependencies); ZookeeperDependencies zookeeperDependencies) {
this.serviceId = getServiceIdFromDepsOrClientName(clientConfig,
zookeeperDependencies);
} }
private String getServiceIdFromDepsOrClientName(IClientConfig clientConfig, ZookeeperDependencies zookeeperDependencies) { private String getServiceIdFromDepsOrClientName(IClientConfig clientConfig,
String serviceIdFromDeps = zookeeperDependencies.getPathForAlias(clientConfig.getClientName()); ZookeeperDependencies zookeeperDependencies) {
return StringUtils.hasText(serviceIdFromDeps) ? serviceIdFromDeps : clientConfig.getClientName(); String serviceIdFromDeps = zookeeperDependencies
.getPathForAlias(clientConfig.getClientName());
return StringUtils.hasText(serviceIdFromDeps) ? serviceIdFromDeps
: clientConfig.getClientName();
} }
@Override @Override
@@ -89,8 +95,10 @@ public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
List<ZookeeperServer> servers = new ArrayList<>(); List<ZookeeperServer> servers = new ArrayList<>();
for (ServiceInstance<ZookeeperInstance> instance : instances) { for (ServiceInstance<ZookeeperInstance> instance : instances) {
String instanceStatus = null; String instanceStatus = null;
if (instance.getPayload() != null && instance.getPayload().getMetadata() != null) { if (instance.getPayload() != null
instanceStatus = instance.getPayload().getMetadata().get(INSTANCE_STATUS_KEY); && instance.getPayload().getMetadata() != null) {
instanceStatus = instance.getPayload().getMetadata()
.get(INSTANCE_STATUS_KEY);
} }
if (!StringUtils.hasText(instanceStatus) // backwards compatibility if (!StringUtils.hasText(instanceStatus) // backwards compatibility
|| instanceStatus.equalsIgnoreCase(STATUS_UP)) { || instanceStatus.equalsIgnoreCase(STATUS_UP)) {
@@ -104,4 +112,5 @@ public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
} }
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,27 +23,35 @@ import java.util.Map;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
/** /**
* A specific {@link ServiceInstance} describing a zookeeper service instance * A specific {@link ServiceInstance} describing a zookeeper service instance.
* *
* @author Reda.Housni-Alaoui * @author Reda Housni-Alaoui
* @author Tim Ysewyn * @author Tim Ysewyn
* @since 1.1.0 * @since 1.1.0
*/ */
public class ZookeeperServiceInstance implements ServiceInstance { public class ZookeeperServiceInstance implements ServiceInstance {
private final String serviceId; private final String serviceId;
private final String host; private final String host;
private final int port; private final int port;
private final boolean secure; private final boolean secure;
private final URI uri; private final URI uri;
private final Map<String, String> metadata; private final Map<String, String> metadata;
private final org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> serviceInstance; private final org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> serviceInstance;
/** /**
* @param serviceId The service id to be used * @param serviceId The service id to be used
* @param serviceInstance The zookeeper service instance described by this service instance * @param serviceInstance The zookeeper service instance described by this service
* instance
*/ */
public ZookeeperServiceInstance(String serviceId, org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> serviceInstance) { public ZookeeperServiceInstance(String serviceId,
org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> serviceInstance) {
this.serviceId = serviceId; this.serviceId = serviceId;
this.serviceInstance = serviceInstance; this.serviceInstance = serviceInstance;
this.host = this.serviceInstance.getAddress(); this.host = this.serviceInstance.getAddress();
@@ -56,7 +64,8 @@ public class ZookeeperServiceInstance implements ServiceInstance {
this.uri = URI.create(serviceInstance.buildUriSpec()); this.uri = URI.create(serviceInstance.buildUriSpec());
if (serviceInstance.getPayload() != null) { if (serviceInstance.getPayload() != null) {
this.metadata = serviceInstance.getPayload().getMetadata(); this.metadata = serviceInstance.getPayload().getMetadata();
} else { }
else {
this.metadata = new HashMap<>(); this.metadata = new HashMap<>();
} }
} }
@@ -99,4 +108,5 @@ public class ZookeeperServiceInstance implements ServiceInstance {
public org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> getServiceInstance() { public org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> getServiceInstance() {
return this.serviceInstance; return this.serviceInstance;
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import java.util.ArrayList; import java.util.ArrayList;
@@ -10,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.sanitize; import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.sanitize;
@@ -19,6 +36,7 @@ import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.
* {@link ZookeeperDependencies} it will return a list of registered Zookeeper instances * {@link ZookeeperDependencies} it will return a list of registered Zookeeper instances
* corresponding to the ones defined in the dependencies. * corresponding to the ones defined in the dependencies.
* *
* @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*/ */
public class ZookeeperServiceInstances public class ZookeeperServiceInstances
@@ -27,9 +45,13 @@ public class ZookeeperServiceInstances
private static final Log log = LogFactory.getLog(ZookeeperServiceInstances.class); private static final Log log = LogFactory.getLog(ZookeeperServiceInstances.class);
private ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
private final ZookeeperDependencies zookeeperDependencies; private final ZookeeperDependencies zookeeperDependencies;
private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties; private final ZookeeperDiscoveryProperties zookeeperDiscoveryProperties;
private final List<ServiceInstance<ZookeeperInstance>> allInstances; private final List<ServiceInstance<ZookeeperInstance>> allInstances;
private final CuratorFramework curator; private final CuratorFramework curator;
public ZookeeperServiceInstances(CuratorFramework curator, public ZookeeperServiceInstances(CuratorFramework curator,
@@ -74,9 +96,11 @@ public class ZookeeperServiceInstances
try { try {
List<String> children = this.curator.getChildren().forPath(parentPath); List<String> children = this.curator.getChildren().forPath(parentPath);
return iterateOverChildren(accumulator, parentPath, children); return iterateOverChildren(accumulator, parentPath, children);
} catch (Exception e) { }
catch (Exception e) {
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Exception occurred while trying to retrieve children of [" + parentPath + "]", e); log.trace("Exception occurred while trying to retrieve children of ["
+ parentPath + "]", e);
} }
return injectZookeeperServiceInstances(accumulator, parentPath); return injectZookeeperServiceInstances(accumulator, parentPath);
} }
@@ -90,8 +114,7 @@ public class ZookeeperServiceInstances
private Collection<ServiceInstance<ZookeeperInstance>> tryToGetInstances( private Collection<ServiceInstance<ZookeeperInstance>> tryToGetInstances(
String path) { String path) {
try { try {
return getServiceDiscovery() return getServiceDiscovery().queryForInstances(getPathWithoutRoot(path));
.queryForInstances(getPathWithoutRoot(path));
} }
catch (Exception e) { catch (Exception e) {
log.trace("Exception occurred while trying to retrieve instances of [" + path log.trace("Exception occurred while trying to retrieve instances of [" + path
@@ -111,7 +134,8 @@ public class ZookeeperServiceInstances
private List<ServiceInstance<ZookeeperInstance>> injectZookeeperServiceInstances( private List<ServiceInstance<ZookeeperInstance>> injectZookeeperServiceInstances(
List<ServiceInstance<ZookeeperInstance>> accumulator, String name) List<ServiceInstance<ZookeeperInstance>> accumulator, String name)
throws Exception { throws Exception {
Collection<ServiceInstance<ZookeeperInstance>> instances = getServiceDiscovery().queryForInstances(name); Collection<ServiceInstance<ZookeeperInstance>> instances = getServiceDiscovery()
.queryForInstances(name);
accumulator.addAll(convertCollectionToList(instances)); accumulator.addAll(convertCollectionToList(instances));
return accumulator; return accumulator;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,13 +16,15 @@
package org.springframework.cloud.zookeeper.discovery; package org.springframework.cloud.zookeeper.discovery;
import javax.annotation.PreDestroy;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.PreDestroy;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.TreeCache; import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent; import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener; import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
@@ -31,20 +33,24 @@ import org.springframework.context.ApplicationListener;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* A {@link TreeCacheListener} that sends {@link HeartbeatEvent} when an * A {@link TreeCacheListener} that sends {@link HeartbeatEvent} when an entry inside
* entry inside Zookeeper has changed. * Zookeeper has changed.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
*/ */
public class ZookeeperServiceWatch implements public class ZookeeperServiceWatch
ApplicationListener<InstanceRegisteredEvent<?>>, TreeCacheListener, implements ApplicationListener<InstanceRegisteredEvent<?>>, TreeCacheListener,
ApplicationEventPublisherAware { ApplicationEventPublisherAware {
private final CuratorFramework curator; private final CuratorFramework curator;
private final ZookeeperDiscoveryProperties properties; private final ZookeeperDiscoveryProperties properties;
private final AtomicLong cacheChange = new AtomicLong(0); private final AtomicLong cacheChange = new AtomicLong(0);
private ApplicationEventPublisher publisher; private ApplicationEventPublisher publisher;
private TreeCache cache; private TreeCache cache;
public ZookeeperServiceWatch(CuratorFramework curator, public ZookeeperServiceWatch(CuratorFramework curator,
@@ -64,7 +70,8 @@ public class ZookeeperServiceWatch implements
@Override @Override
public void onApplicationEvent(InstanceRegisteredEvent<?> event) { public void onApplicationEvent(InstanceRegisteredEvent<?> event) {
this.cache = TreeCache.newBuilder(this.curator, this.properties.getRoot()).build(); this.cache = TreeCache.newBuilder(this.curator, this.properties.getRoot())
.build();
this.cache.getListenable().addListener(this); this.cache.getListenable().addListener(this);
try { try {
this.cache.start(); this.cache.start();
@@ -82,7 +89,8 @@ public class ZookeeperServiceWatch implements
} }
@Override @Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception { public void childEvent(CuratorFramework client, TreeCacheEvent event)
throws Exception {
if (event.getType().equals(TreeCacheEvent.Type.NODE_ADDED) if (event.getType().equals(TreeCacheEvent.Type.NODE_ADDED)
|| event.getType().equals(TreeCacheEvent.Type.NODE_REMOVED) || event.getType().equals(TreeCacheEvent.Type.NODE_REMOVED)
|| event.getType().equals(TreeCacheEvent.Type.NODE_UPDATED)) { || event.getType().equals(TreeCacheEvent.Type.NODE_UPDATED)) {
@@ -90,4 +98,5 @@ public class ZookeeperServiceWatch implements
this.publisher.publishEvent(new HeartbeatEvent(this, newCacheChange)); this.publisher.publishEvent(new HeartbeatEvent(this, newCacheChange));
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -39,15 +39,19 @@ import org.springframework.core.annotation.Order;
@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false) @ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
@Configuration @Configuration
@Import({ ZookeeperAutoConfiguration.class, ZookeeperDiscoveryClientConfiguration.class, @Import({ ZookeeperAutoConfiguration.class, ZookeeperDiscoveryClientConfiguration.class,
CuratorServiceDiscoveryAutoConfiguration.class, ZookeeperDiscoveryAutoConfiguration.class}) CuratorServiceDiscoveryAutoConfiguration.class,
ZookeeperDiscoveryAutoConfiguration.class })
@Order(0) @Order(0)
public class ZookeeperDiscoveryClientConfigServiceBootstrapConfiguration { public class ZookeeperDiscoveryClientConfigServiceBootstrapConfiguration {
@Bean @Bean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) { public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(
ZookeeperDiscoveryProperties properties = new ZookeeperDiscoveryProperties(inetUtils); InetUtils inetUtils) {
ZookeeperDiscoveryProperties properties = new ZookeeperDiscoveryProperties(
inetUtils);
// for bootstrap, registration is not needed, just discovery client // for bootstrap, registration is not needed, just discovery client
properties.setRegister(false); properties.setRegister(false);
return properties; return properties;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,13 +24,14 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
/** /**
* Annotation to turn off a feature if Zookeeper dependencies have NOT been passed * Annotation to turn off a feature if Zookeeper dependencies have NOT been passed.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*/ */
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Conditional(DependenciesNotPassedCondition.class) @Conditional(DependenciesNotPassedCondition.class)
public @interface ConditionalOnDependenciesNotPassed { public @interface ConditionalOnDependenciesNotPassed {
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,14 +24,15 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
/** /**
* Annotation to turn on a feature if Zookeeper dependencies have been passed. * Annotation to turn on a feature if Zookeeper dependencies have been passed. Also checks
* Also checks if switch for zookeeper dependencies is turned on. * if switch for zookeeper dependencies is turned on.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*/ */
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Conditional(DependenciesPassedCondition.class) @Conditional(DependenciesPassedCondition.class)
public @interface ConditionalOnDependenciesPassed { public @interface ConditionalOnDependenciesPassed {
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -27,13 +27,12 @@ import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList; import com.netflix.loadbalancer.ServerList;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* LoadBalancer that delegates to other rules depending on the provided load balancing strategy * LoadBalancer that delegates to other rules depending on the provided load balancing
* in the {@link ZookeeperDependency#getLoadBalancerType()} * strategy in the {@link ZookeeperDependency#getLoadBalancerType()}.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -46,7 +45,8 @@ public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer
private final ZookeeperDependencies zookeeperDependencies; private final ZookeeperDependencies zookeeperDependencies;
public DependenciesBasedLoadBalancer(ZookeeperDependencies zookeeperDependencies, ServerList<?> serverList, IClientConfig config, IPing iPing) { public DependenciesBasedLoadBalancer(ZookeeperDependencies zookeeperDependencies,
ServerList<?> serverList, IClientConfig config, IPing iPing) {
super(config); super(config);
this.zookeeperDependencies = zookeeperDependencies; this.zookeeperDependencies = zookeeperDependencies;
setServersList(serverList.getInitialListOfServers()); setServersList(serverList.getInitialListOfServers());
@@ -59,17 +59,24 @@ public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer
String keyAsString; String keyAsString;
if ("default".equals(key)) { // this is the default hint, use name instead if ("default".equals(key)) { // this is the default hint, use name instead
keyAsString = getName(); keyAsString = getName();
} else { }
else {
keyAsString = (String) key; keyAsString = (String) key;
} }
ZookeeperDependency dependency = this.zookeeperDependencies.getDependencyForAlias(keyAsString); ZookeeperDependency dependency = this.zookeeperDependencies
log.debug(String.format("Current dependencies are [%s]", this.zookeeperDependencies)); .getDependencyForAlias(keyAsString);
log.debug(String.format("Current dependencies are [%s]",
this.zookeeperDependencies));
if (dependency == null) { if (dependency == null) {
log.debug(String.format("No dependency found for alias [%s] - will use the default rule which is [%s]", keyAsString, this.rule)); log.debug(String.format(
"No dependency found for alias [%s] - will use the default rule which is [%s]",
keyAsString, this.rule));
return this.rule.choose(key); return this.rule.choose(key);
} }
cacheEntryIfMissing(keyAsString, dependency); cacheEntryIfMissing(keyAsString, dependency);
log.debug(String.format("Will try to retrieve dependency for key [%s]. Current cache contents [%s]", keyAsString, this.ruleCache)); log.debug(String.format(
"Will try to retrieve dependency for key [%s]. Current cache contents [%s]",
keyAsString, this.ruleCache));
updateListOfServers(); updateListOfServers();
return this.ruleCache.get(keyAsString).choose(key); return this.ruleCache.get(keyAsString).choose(key);
} }
@@ -77,20 +84,21 @@ public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer
private void cacheEntryIfMissing(String keyAsString, ZookeeperDependency dependency) { private void cacheEntryIfMissing(String keyAsString, ZookeeperDependency dependency) {
if (!this.ruleCache.containsKey(keyAsString)) { if (!this.ruleCache.containsKey(keyAsString)) {
log.debug(String.format("Cache doesn't contain entry for [%s]", keyAsString)); log.debug(String.format("Cache doesn't contain entry for [%s]", keyAsString));
this.ruleCache.put(keyAsString, chooseRuleForLoadBalancerType(dependency.getLoadBalancerType())); this.ruleCache.put(keyAsString,
chooseRuleForLoadBalancerType(dependency.getLoadBalancerType()));
} }
} }
private IRule chooseRuleForLoadBalancerType(LoadBalancerType type) { private IRule chooseRuleForLoadBalancerType(LoadBalancerType type) {
switch (type) { switch (type) {
case ROUND_ROBIN: case ROUND_ROBIN:
return getRoundRobinRule(); return getRoundRobinRule();
case RANDOM: case RANDOM:
return getRandomRule(); return getRandomRule();
case STICKY: case STICKY:
return getStickyRule(); return getStickyRule();
default: default:
throw new IllegalArgumentException("Unknown load balancer type " + type); throw new IllegalArgumentException("Unknown load balancer type " + type);
} }
} }
@@ -109,4 +117,5 @@ public class DependenciesBasedLoadBalancer extends DynamicServerListLoadBalancer
stickyRule.setLoadBalancer(this); stickyRule.setLoadBalancer(this);
return stickyRule; return stickyRule;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.dependency; package org.springframework.cloud.zookeeper.discovery.dependency;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
@@ -20,7 +21,7 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
/** /**
* Inverse of the {@link ConditionalOnDependenciesPassed} condition. * Inverse of the {@link ConditionalOnDependenciesPassed} condition.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -28,7 +29,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
public class DependenciesNotPassedCondition extends DependenciesPassedCondition { public class DependenciesNotPassedCondition extends DependenciesPassedCondition {
@Override @Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionOutcome propertiesSet = super.getMatchOutcome(context, metadata); ConditionOutcome propertiesSet = super.getMatchOutcome(context, metadata);
return ConditionOutcome.inverse(propertiesSet); return ConditionOutcome.inverse(propertiesSet);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.dependency; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.Collections; import java.util.Collections;
@@ -26,8 +27,8 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
/** /**
* Condition that verifies if the Dependencies have been passed in an appropriate * Condition that verifies if the Dependencies have been passed in an appropriate place in
* place in the application properties. * the application properties.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -36,21 +37,26 @@ public class DependenciesPassedCondition extends SpringBootCondition {
private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable
.mapOf(String.class, String.class); .mapOf(String.class, String.class);
private static final String ZOOKEEPER_DEPENDENCIES_PROP = "spring.cloud.zookeeper.dependencies"; private static final String ZOOKEEPER_DEPENDENCIES_PROP = "spring.cloud.zookeeper.dependencies";
@Override @Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
Map<String, String> subProperties = Binder.get(context.getEnvironment()) Map<String, String> subProperties = Binder.get(context.getEnvironment())
.bind(ZOOKEEPER_DEPENDENCIES_PROP, STRING_STRING_MAP).orElseGet(Collections::emptyMap); .bind(ZOOKEEPER_DEPENDENCIES_PROP, STRING_STRING_MAP)
.orElseGet(Collections::emptyMap);
if (!subProperties.isEmpty()) { if (!subProperties.isEmpty()) {
return ConditionOutcome.match("Dependencies are defined in configuration"); return ConditionOutcome.match("Dependencies are defined in configuration");
} }
Boolean dependenciesEnabled = context.getEnvironment() Boolean dependenciesEnabled = context.getEnvironment().getProperty(
.getProperty("spring.cloud.zookeeper.dependency.enabled", Boolean.class, false); "spring.cloud.zookeeper.dependency.enabled", Boolean.class, false);
if (dependenciesEnabled) { if (dependenciesEnabled) {
return ConditionOutcome.match("Dependencies are not defined in configuration, but switch is turned on"); return ConditionOutcome.match(
"Dependencies are not defined in configuration, but switch is turned on");
} }
return ConditionOutcome.noMatch("No dependencies have been passed for the service"); return ConditionOutcome
.noMatch("No dependencies have been passed for the service");
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -27,10 +27,10 @@ import org.springframework.core.env.MapPropertySource;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* EnvironmentPostProcessor that sets spring.application.name. * EnvironmentPostProcessor that sets spring.application.name. Specifically, if
* Specifically, if spring.application.name doesn't contain a / and * spring.application.name doesn't contain a / and spring.cloud.zookeeper.prefix has text,
* spring.cloud.zookeeper.prefix has text, it sets spring.application.name * it sets spring.application.name to
* to /${spring.cloud.zookeeper.prefix}/${spring.application.name} * /${spring.cloud.zookeeper.prefix}/${spring.application.name}
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
@@ -41,11 +41,13 @@ public class DependencyEnvironmentPostProcessor
// after ConfigFileEnvironmentPostProcessorr // after ConfigFileEnvironmentPostProcessorr
private int order = ConfigFileApplicationListener.DEFAULT_ORDER + 1; private int order = ConfigFileApplicationListener.DEFAULT_ORDER + 1;
@Override public int getOrder() { @Override
public int getOrder() {
return this.order; return this.order;
} }
@Override public void postProcessEnvironment(ConfigurableEnvironment environment, @Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) { SpringApplication application) {
String appName = environment.getProperty("spring.application.name"); String appName = environment.getProperty("spring.application.name");
if (StringUtils.hasText(appName) && !appName.contains("/")) { if (StringUtils.hasText(appName) && !appName.contains("/")) {
@@ -61,11 +63,12 @@ public class DependencyEnvironmentPostProcessor
} }
prefixedName.append(appName); prefixedName.append(appName);
MapPropertySource propertySource = new MapPropertySource( MapPropertySource propertySource = new MapPropertySource(
"zookeeperDependencyEnvironment", Collections "zookeeperDependencyEnvironment",
.singletonMap("spring.application.name", Collections.singletonMap("spring.application.name",
(Object) prefixedName.toString())); (Object) prefixedName.toString()));
environment.getPropertySources().addFirst(propertySource); environment.getPropertySources().addFirst(propertySource);
} }
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,27 +23,27 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import feign.Client;
import feign.Request;
import feign.Response;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration; import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled; import org.springframework.cloud.zookeeper.ConditionalOnZookeeperEnabled;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import feign.Client;
import feign.Request;
import feign.Response;
/** /**
* Configuration for ensuring that headers are set for a given dependency when * Configuration for ensuring that headers are set for a given dependency when Feign is
* Feign is used. * used.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -53,32 +53,40 @@ import feign.Response;
@ConditionalOnZookeeperEnabled @ConditionalOnZookeeperEnabled
@ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.headers.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.headers.enabled", matchIfMissing = true)
@ConditionalOnClass({ Client.class, LoadBalancerFeignClient.class }) @ConditionalOnClass({ Client.class, LoadBalancerFeignClient.class })
@AutoConfigureAfter({ RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class }) @AutoConfigureAfter({ RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class })
public class DependencyFeignClientAutoConfiguration { public class DependencyFeignClientAutoConfiguration {
@Autowired(required = false) private LoadBalancerFeignClient ribbonClient;
@Autowired private ZookeeperDependencies zookeeperDependencies; @Autowired(required = false)
@Autowired private CachingSpringLoadBalancerFactory loadBalancerFactory; private LoadBalancerFeignClient ribbonClient;
@Autowired private SpringClientFactory springClientFactory;
@Autowired
private ZookeeperDependencies zookeeperDependencies;
@Autowired
private CachingSpringLoadBalancerFactory loadBalancerFactory;
@Autowired
private SpringClientFactory springClientFactory;
@Bean @Bean
@Primary @Primary
Client dependencyBasedFeignClient() { Client dependencyBasedFeignClient() {
return new LoadBalancerFeignClient( return new LoadBalancerFeignClient(new Client.Default(null, null),
new Client.Default(null, null), this.loadBalancerFactory, this.springClientFactory) { this.loadBalancerFactory, this.springClientFactory) {
@Override @Override
public Response execute(Request request, Request.Options options) public Response execute(Request request, Request.Options options)
throws IOException { throws IOException {
URI asUri = URI.create(request.url()); URI asUri = URI.create(request.url());
String clientName = asUri.getHost(); String clientName = asUri.getHost();
ZookeeperDependency dependencyForAlias = ZookeeperDependency dependencyForAlias = DependencyFeignClientAutoConfiguration.this.zookeeperDependencies
DependencyFeignClientAutoConfiguration.this.zookeeperDependencies
.getDependencyForAlias(clientName); .getDependencyForAlias(clientName);
Map<String, Collection<String>> headers = getUpdatedHeadersIfPossible( Map<String, Collection<String>> headers = getUpdatedHeadersIfPossible(
request, dependencyForAlias); request, dependencyForAlias);
if (DependencyFeignClientAutoConfiguration.this.ribbonClient != null) { if (DependencyFeignClientAutoConfiguration.this.ribbonClient != null) {
return DependencyFeignClientAutoConfiguration.this.ribbonClient.execute( return DependencyFeignClientAutoConfiguration.this.ribbonClient
request(request, headers), options); .execute(request(request, headers), options);
} }
return super.execute(request(request, headers), options); return super.execute(request(request, headers), options);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -52,33 +53,45 @@ import org.springframework.web.client.RestTemplate;
@AutoConfigureAfter(DependencyRibbonAutoConfiguration.class) @AutoConfigureAfter(DependencyRibbonAutoConfiguration.class)
public class DependencyRestTemplateAutoConfiguration { public class DependencyRestTemplateAutoConfiguration {
@Autowired @LoadBalanced RestTemplate restTemplate; @Autowired
@Autowired ZookeeperDependencies zookeeperDependencies; @LoadBalanced
RestTemplate restTemplate;
@Autowired
ZookeeperDependencies zookeeperDependencies;
@PostConstruct @PostConstruct
void customizeRestTemplate() { void customizeRestTemplate() {
this.restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() { this.restTemplate.getInterceptors().add(new ClientHttpRequestInterceptor() {
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
String clientName = request.getURI().getHost(); String clientName = request.getURI().getHost();
ZookeeperDependency dependencyForAlias = DependencyRestTemplateAutoConfiguration.this.zookeeperDependencies.getDependencyForAlias(clientName); ZookeeperDependency dependencyForAlias = DependencyRestTemplateAutoConfiguration.this.zookeeperDependencies
HttpHeaders headers = getUpdatedHeadersIfPossible(request, dependencyForAlias); .getDependencyForAlias(clientName);
HttpHeaders headers = getUpdatedHeadersIfPossible(request,
dependencyForAlias);
request.getHeaders().putAll(headers); request.getHeaders().putAll(headers);
return execution.execute(request, body); return execution.execute(request, body);
} }
private HttpHeaders getUpdatedHeadersIfPossible(HttpRequest request, ZookeeperDependency dependencyForAlias) { private HttpHeaders getUpdatedHeadersIfPossible(HttpRequest request,
ZookeeperDependency dependencyForAlias) {
HttpHeaders httpHeaders = new HttpHeaders(); HttpHeaders httpHeaders = new HttpHeaders();
if (dependencyForAlias != null) { if (dependencyForAlias != null) {
Map<String, Collection<String>> updatedHeaders = dependencyForAlias.getUpdatedHeaders(convertHeadersFromListToCollection(request.getHeaders())); Map<String, Collection<String>> updatedHeaders = dependencyForAlias
httpHeaders.putAll(convertHeadersFromCollectionToList(updatedHeaders)); .getUpdatedHeaders(convertHeadersFromListToCollection(
request.getHeaders()));
httpHeaders
.putAll(convertHeadersFromCollectionToList(updatedHeaders));
return httpHeaders; return httpHeaders;
} }
httpHeaders.putAll(request.getHeaders()); httpHeaders.putAll(request.getHeaders());
return httpHeaders; return httpHeaders;
} }
private Map<String, Collection<String>> convertHeadersFromListToCollection(HttpHeaders headers) { private Map<String, Collection<String>> convertHeadersFromListToCollection(
HttpHeaders headers) {
Map<String, Collection<String>> transformedHeaders = new HashMap<>(); Map<String, Collection<String>> transformedHeaders = new HashMap<>();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) { for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
transformedHeaders.put(entry.getKey(), entry.getValue()); transformedHeaders.put(entry.getKey(), entry.getValue());
@@ -86,10 +99,12 @@ public class DependencyRestTemplateAutoConfiguration {
return transformedHeaders; return transformedHeaders;
} }
private Map<String, List<String>> convertHeadersFromCollectionToList(Map<String, Collection<String>> headers) { private Map<String, List<String>> convertHeadersFromCollectionToList(
Map<String, Collection<String>> headers) {
Map<String, List<String>> transformedHeaders = new HashMap<>(); Map<String, List<String>> transformedHeaders = new HashMap<>();
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) { for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
transformedHeaders.put(entry.getKey(), new ArrayList<>(entry.getValue())); transformedHeaders.put(entry.getKey(),
new ArrayList<>(entry.getValue()));
} }
return transformedHeaders; return transformedHeaders;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@ package org.springframework.cloud.zookeeper.discovery.dependency;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -38,7 +38,7 @@ import org.springframework.context.annotation.Configuration;
/** /**
* *
* Provides LoadBalancerClient that at runtime can pick proper load balancing strategy * Provides LoadBalancerClient that at runtime can pick proper load balancing strategy
* basing on the Zookeeper dependencies from properties * basing on the Zookeeper dependencies from properties.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -50,25 +50,33 @@ import org.springframework.context.annotation.Configuration;
@AutoConfigureBefore(RibbonAutoConfiguration.class) @AutoConfigureBefore(RibbonAutoConfiguration.class)
public class DependencyRibbonAutoConfiguration { public class DependencyRibbonAutoConfiguration {
private static final Log log = LogFactory.getLog(DependencyRibbonAutoConfiguration.class); private static final Log log = LogFactory
.getLog(DependencyRibbonAutoConfiguration.class);
@Autowired ApplicationContext applicationContext; @Autowired
ApplicationContext applicationContext;
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.ribbon.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.zookeeper.dependency.ribbon.enabled", matchIfMissing = true)
public LoadBalancerClient loadBalancerClient(SpringClientFactory springClientFactory) { public LoadBalancerClient loadBalancerClient(
SpringClientFactory springClientFactory) {
return new RibbonLoadBalancerClient(springClientFactory) { return new RibbonLoadBalancerClient(springClientFactory) {
@Override @Override
protected Server getServer(String serviceId) { protected Server getServer(String serviceId) {
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId); ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
return loadBalancer == null ? null : chooseServerByServiceIdOrDefault(loadBalancer, serviceId); return loadBalancer == null ? null
: chooseServerByServiceIdOrDefault(loadBalancer, serviceId);
} }
private Server chooseServerByServiceIdOrDefault(ILoadBalancer loadBalancer, String serviceId) { private Server chooseServerByServiceIdOrDefault(ILoadBalancer loadBalancer,
log.debug(String.format("Dependencies are set - will try to load balance via provided load balancer [%s] for key [%s]", loadBalancer, serviceId)); String serviceId) {
log.debug(String.format(
"Dependencies are set - will try to load balance via provided load balancer [%s] for key [%s]",
loadBalancer, serviceId));
Server server = loadBalancer.chooseServer(serviceId); Server server = loadBalancer.chooseServer(serviceId);
log.debug(String.format("Retrieved server [%s] via load balancer", server)); log.debug(
String.format("Retrieved server [%s] via load balancer", server));
return server != null ? server : loadBalancer.chooseServer("default"); return server != null ? server : loadBalancer.chooseServer("default");
} }
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.dependency; package org.springframework.cloud.zookeeper.discovery.dependency;
/** /**
@@ -21,5 +22,10 @@ package org.springframework.cloud.zookeeper.discovery.dependency;
* @since 1.0.0 * @since 1.0.0
*/ */
public enum LoadBalancerType { public enum LoadBalancerType {
/**
* Valid load balancer types.
*/
STICKY, RANDOM, ROUND_ROBIN STICKY, RANDOM, ROUND_ROBIN
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -37,9 +36,13 @@ import org.apache.commons.logging.LogFactory;
* @since 1.0.0 * @since 1.0.0
*/ */
public class StickyRule extends AbstractLoadBalancerRule { public class StickyRule extends AbstractLoadBalancerRule {
private static final Log log = LogFactory.getLog(StickyRule.class); private static final Log log = LogFactory.getLog(StickyRule.class);
private final IRule masterStrategy; private final IRule masterStrategy;
private final AtomicReference<Server> ourInstance = new AtomicReference<>(null); private final AtomicReference<Server> ourInstance = new AtomicReference<>(null);
private final AtomicInteger instanceNumber = new AtomicInteger(-1); private final AtomicInteger instanceNumber = new AtomicInteger(-1);
public StickyRule(IRule masterStrategy) { public StickyRule(IRule masterStrategy) {
@@ -70,10 +73,10 @@ public class StickyRule extends AbstractLoadBalancerRule {
} }
/** /**
* Each time a new instance is picked, an internal counter is incremented. This way you * Each time a new instance is picked, an internal counter is incremented. This way
* can track when/if the instance changes. The instance can change when the selected instance * you can track when/if the instance changes. The instance can change when the
* is not in the current list of instances returned by the instance provider * selected instance is not in the current list of instances returned by the instance
* * provider
* @return instance number * @return instance number
*/ */
public int getInstanceNumber() { public int getInstanceNumber() {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.Arrays; import java.util.Arrays;
@@ -12,29 +28,38 @@ import org.springframework.util.StringUtils;
* @since 1.0.0 * @since 1.0.0
*/ */
public class StubsConfiguration { public class StubsConfiguration {
private static final String DEFAULT_STUBS_CLASSIFIER = "stubs"; private static final String DEFAULT_STUBS_CLASSIFIER = "stubs";
private static final String STUB_COLON_DELIMITER = ":"; private static final String STUB_COLON_DELIMITER = ":";
private static final String PATH_SLASH_DELIMITER = "/"; private static final String PATH_SLASH_DELIMITER = "/";
private final String stubsGroupId; private final String stubsGroupId;
private final String stubsArtifactId; private final String stubsArtifactId;
private final String stubsClassifier; private final String stubsClassifier;
public StubsConfiguration(String stubsGroupId, String stubsArtifactId, String stubsClassifier) { public StubsConfiguration(String stubsGroupId, String stubsArtifactId,
String stubsClassifier) {
this.stubsGroupId = stubsGroupId; this.stubsGroupId = stubsGroupId;
this.stubsArtifactId = stubsArtifactId; this.stubsArtifactId = stubsArtifactId;
this.stubsClassifier = StringUtils.hasText(stubsClassifier) ? stubsClassifier : DEFAULT_STUBS_CLASSIFIER; this.stubsClassifier = StringUtils.hasText(stubsClassifier) ? stubsClassifier
: DEFAULT_STUBS_CLASSIFIER;
} }
public StubsConfiguration(String stubPath) { public StubsConfiguration(String stubPath) {
String[] parsedPath = parsedStubPathEmptyByDefault(stubPath, STUB_COLON_DELIMITER); String[] parsedPath = parsedStubPathEmptyByDefault(stubPath,
STUB_COLON_DELIMITER);
this.stubsGroupId = parsedPath[0]; this.stubsGroupId = parsedPath[0];
this.stubsArtifactId = parsedPath[1]; this.stubsArtifactId = parsedPath[1];
this.stubsClassifier = parsedPath[2]; this.stubsClassifier = parsedPath[2];
} }
public StubsConfiguration(DependencyPath path) { public StubsConfiguration(DependencyPath path) {
String[] parsedPath = parsedDependencyPathEmptyByDefault(path.getPath(), PATH_SLASH_DELIMITER); String[] parsedPath = parsedDependencyPathEmptyByDefault(path.getPath(),
PATH_SLASH_DELIMITER);
this.stubsGroupId = parsedPath[0]; this.stubsGroupId = parsedPath[0];
this.stubsArtifactId = parsedPath[1]; this.stubsArtifactId = parsedPath[1];
this.stubsClassifier = parsedPath[2]; this.stubsClassifier = parsedPath[2];
@@ -48,9 +73,10 @@ public class StubsConfiguration {
if (splitPath.length >= 2) { if (splitPath.length >= 2) {
stubsGroupId = splitPath[0]; stubsGroupId = splitPath[0];
stubsArtifactId = splitPath[1]; stubsArtifactId = splitPath[1];
stubsClassifier = splitPath.length == 3 ? splitPath[2] : DEFAULT_STUBS_CLASSIFIER; stubsClassifier = splitPath.length == 3 ? splitPath[2]
: DEFAULT_STUBS_CLASSIFIER;
} }
return new String[]{stubsGroupId, stubsArtifactId, stubsClassifier}; return new String[] { stubsGroupId, stubsArtifactId, stubsClassifier };
} }
private String[] parsedDependencyPathEmptyByDefault(String path, String delimiter) { private String[] parsedDependencyPathEmptyByDefault(String path, String delimiter) {
@@ -66,18 +92,20 @@ public class StubsConfiguration {
stubsArtifactId = lastElement; stubsArtifactId = lastElement;
stubsClassifier = DEFAULT_STUBS_CLASSIFIER; stubsClassifier = DEFAULT_STUBS_CLASSIFIER;
} }
return new String[]{stubsGroupId, stubsArtifactId, stubsClassifier}; return new String[] { stubsGroupId, stubsArtifactId, stubsClassifier };
} }
private boolean isDefined() { private boolean isDefined() {
return StringUtils.hasText(this.stubsGroupId) && StringUtils.hasText(this.stubsArtifactId); return StringUtils.hasText(this.stubsGroupId)
&& StringUtils.hasText(this.stubsArtifactId);
} }
public String toColonSeparatedDependencyNotation() { public String toColonSeparatedDependencyNotation() {
if(!isDefined()) { if (!isDefined()) {
return ""; return "";
} }
return StringUtils.collectionToDelimitedString(Arrays.asList(getStubsGroupId(), getStubsArtifactId(), getStubsClassifier()), STUB_COLON_DELIMITER); return StringUtils.collectionToDelimitedString(Arrays.asList(getStubsGroupId(),
getStubsArtifactId(), getStubsClassifier()), STUB_COLON_DELIMITER);
} }
public String getStubsGroupId() { public String getStubsGroupId() {
@@ -93,9 +121,10 @@ public class StubsConfiguration {
} }
/** /**
* Marker class to discern between the stubs location and dependency registration path * Marker class to discern between the stubs location and dependency registration path.
*/ */
static class DependencyPath { public static class DependencyPath {
private final String path; private final String path;
public DependencyPath(String path) { public DependencyPath(String path) {
@@ -105,5 +134,7 @@ public class StubsConfiguration {
public String getPath() { public String getPath() {
return this.path; return this.path;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,15 +13,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.dependency; package org.springframework.cloud.zookeeper.discovery.dependency;
import javax.annotation.PostConstruct;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.zookeeper.discovery.dependency.StubsConfiguration.DependencyPath; import org.springframework.cloud.zookeeper.discovery.dependency.StubsConfiguration.DependencyPath;
@@ -30,7 +32,7 @@ import org.springframework.util.StringUtils;
import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.sanitize; import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.sanitize;
/** /**
* Representation of this service's dependencies in Zookeeper * Representation of this service's dependencies in Zookeeper.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -39,18 +41,18 @@ import static org.springframework.cloud.zookeeper.discovery.DependencyPathUtils.
public class ZookeeperDependencies { public class ZookeeperDependencies {
/** /**
* Common prefix that will be applied to all Zookeeper dependencies' paths * Common prefix that will be applied to all Zookeeper dependencies' paths.
*/ */
private String prefix = ""; private String prefix = "";
/** /**
* Mapping of alias to ZookeeperDependency. From Ribbon perspective the alias * Mapping of alias to ZookeeperDependency. From Ribbon perspective the alias is
* is actually serviceID since Ribbon can't accept nested structures in serviceID * actually serviceID since Ribbon can't accept nested structures in serviceID.
*/ */
private Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>(); private Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>();
/** /**
* Default health endpoint that will be checked to verify that a dependency is alive * Default health endpoint that will be checked to verify that a dependency is alive.
*/ */
@Value("${spring.cloud.zookeeper.dependency.ribbon.loadbalancer.defaulthealthendpoint:/health}") @Value("${spring.cloud.zookeeper.dependency.ribbon.loadbalancer.defaulthealthendpoint:/health}")
private String defaultHealthEndpoint; private String defaultHealthEndpoint;
@@ -60,7 +62,8 @@ public class ZookeeperDependencies {
if (StringUtils.hasText(this.prefix)) { if (StringUtils.hasText(this.prefix)) {
this.prefix = sanitize(this.prefix); this.prefix = sanitize(this.prefix);
} }
for (Map.Entry<String, ZookeeperDependency> entry : this.dependencies.entrySet()) { for (Map.Entry<String, ZookeeperDependency> entry : this.dependencies
.entrySet()) {
ZookeeperDependency value = entry.getValue(); ZookeeperDependency value = entry.getValue();
if (!StringUtils.hasText(value.getPath())) { if (!StringUtils.hasText(value.getPath())) {
@@ -79,8 +82,10 @@ public class ZookeeperDependencies {
private void setStubDefinition(ZookeeperDependency value) { private void setStubDefinition(ZookeeperDependency value) {
if (!StringUtils.hasText(value.getStubs())) { if (!StringUtils.hasText(value.getStubs())) {
value.setStubsConfiguration(new StubsConfiguration(new DependencyPath(value.getPath()))); value.setStubsConfiguration(
} else { new StubsConfiguration(new DependencyPath(value.getPath())));
}
else {
value.setStubsConfiguration(new StubsConfiguration(value.getStubs())); value.setStubsConfiguration(new StubsConfiguration(value.getStubs()));
} }
} }
@@ -94,7 +99,8 @@ public class ZookeeperDependencies {
} }
public ZookeeperDependency getDependencyForPath(final String path) { public ZookeeperDependency getDependencyForPath(final String path) {
for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies.entrySet()) { for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies
.entrySet()) {
if (zookeeperDependencyEntry.getValue().getPath().equals(path)) { if (zookeeperDependencyEntry.getValue().getPath().equals(path)) {
return zookeeperDependencyEntry.getValue(); return zookeeperDependencyEntry.getValue();
} }
@@ -103,7 +109,8 @@ public class ZookeeperDependencies {
} }
public ZookeeperDependency getDependencyForAlias(final String alias) { public ZookeeperDependency getDependencyForAlias(final String alias) {
for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies.entrySet()) { for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies
.entrySet()) {
if (zookeeperDependencyEntry.getKey().equals(alias)) { if (zookeeperDependencyEntry.getKey().equals(alias)) {
return zookeeperDependencyEntry.getValue(); return zookeeperDependencyEntry.getValue();
} }
@@ -120,7 +127,8 @@ public class ZookeeperDependencies {
} }
public String getAliasForPath(final String path) { public String getAliasForPath(final String path) {
for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies.entrySet()) { for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies
.entrySet()) {
if (zookeeperDependencyEntry.getValue().getPath().equals(path)) { if (zookeeperDependencyEntry.getValue().getPath().equals(path)) {
return zookeeperDependencyEntry.getKey(); return zookeeperDependencyEntry.getKey();
} }
@@ -130,7 +138,8 @@ public class ZookeeperDependencies {
public Collection<String> getDependencyNames() { public Collection<String> getDependencyNames() {
List<String> names = new ArrayList<>(); List<String> names = new ArrayList<>();
for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies.entrySet()) { for (Map.Entry<String, ZookeeperDependency> zookeeperDependencyEntry : this.dependencies
.entrySet()) {
names.add(zookeeperDependencyEntry.getValue().getPath()); names.add(zookeeperDependencyEntry.getValue().getPath());
} }
return names; return names;
@@ -165,8 +174,10 @@ public class ZookeeperDependencies {
final StringBuffer sb = new StringBuffer("ZookeeperDependencies{"); final StringBuffer sb = new StringBuffer("ZookeeperDependencies{");
sb.append("prefix='").append(this.prefix).append('\''); sb.append("prefix='").append(this.prefix).append('\'');
sb.append(", dependencies=").append(this.dependencies); sb.append(", dependencies=").append(this.dependencies);
sb.append(", defaultHealthEndpoint='").append(this.defaultHealthEndpoint).append('\''); sb.append(", defaultHealthEndpoint='").append(this.defaultHealthEndpoint)
.append('\'');
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.dependency; package org.springframework.cloud.zookeeper.discovery.dependency;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,58 +34,64 @@ import static java.util.Collections.singletonList;
public class ZookeeperDependency { public class ZookeeperDependency {
private static final String VERSION_PLACEHOLDER_REGEX = "\\$version"; private static final String VERSION_PLACEHOLDER_REGEX = "\\$version";
private static final String CONTENT_TYPE_HEADER = "Content-Type"; private static final String CONTENT_TYPE_HEADER = "Content-Type";
/** /**
* Path under which the dependency is registered in Zookeeper. The common prefix * Path under which the dependency is registered in Zookeeper. The common prefix
* {@link ZookeeperDependencies#prefix} will be applied to this path * {@link ZookeeperDependencies#prefix} will be applied to this path.
*/ */
private String path; private String path;
/** /**
* Type of load balancer that should be used for this particular dependency * Type of load balancer that should be used for this particular dependency.
*/ */
private LoadBalancerType loadBalancerType = LoadBalancerType.ROUND_ROBIN; private LoadBalancerType loadBalancerType = LoadBalancerType.ROUND_ROBIN;
/** /**
* Content type template with {@code $version} placeholder which will be filled * Content type template with {@code $version} placeholder which will be filled by the
* by the {@link ZookeeperDependency#version} variable. * {@link ZookeeperDependency#version} variable.
* <p/> * <p/>
* e.g. {@code 'application/vnd.some-service.$version+json'} * e.g. {@code 'application/vnd.some-service.$version+json'}
*/ */
private String contentTypeTemplate = ""; private String contentTypeTemplate = "";
/** /**
* Provide the current version number of the dependency. This version will be placed under the * Provide the current version number of the dependency. This version will be placed
* {@code $version} placeholder in {@link ZookeeperDependency#contentTypeTemplate} * under the {@code $version} placeholder in
* {@link ZookeeperDependency#contentTypeTemplate}.
*/ */
private String version = ""; private String version = "";
/** /**
* You can provide a map of default headers that should be attached when sending a message to the dependency * You can provide a map of default headers that should be attached when sending a
* message to the dependency.
*/ */
private Map<String, Collection<String>> headers = new HashMap<>(); private Map<String, Collection<String>> headers = new HashMap<>();
/** /**
* If set to true - if the dependency is not present on startup then the application will not boot successfully * If set to true - if the dependency is not present on startup then the application
* will not boot successfully.
* <p/> * <p/>
* {@link org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier;} * {@link org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier}
* {@link org.springframework.cloud.zookeeper.discovery.watcher.DefaultDependencyWatcher} * {@link org.springframework.cloud.zookeeper.discovery.watcher.DefaultDependencyWatcher}
*/ */
private boolean required; private boolean required;
/** /**
* Colon separated notation of the stubs. E.g. {@code org.springframework:zookeeper-sample:stubs}. If not provided * Colon separated notation of the stubs. E.g.
* the {@code path} will be parsed to try to split it into groupId and artifactId. If not provided the classifier * {@code org.springframework:zookeeper-sample:stubs}. If not provided the
* will by default equal {@code stubs} * {@code path} will be parsed to try to split it into groupId and artifactId. If not
* provided the classifier will by default equal {@code stubs}
*/ */
private String stubs; private String stubs;
public ZookeeperDependency() { public ZookeeperDependency() {
} }
public ZookeeperDependency(String path, LoadBalancerType loadBalancerType, String contentTypeTemplate, public ZookeeperDependency(String path, LoadBalancerType loadBalancerType,
String version, Map<String, Collection<String>> headers, boolean required, String stubs) { String contentTypeTemplate, String version,
Map<String, Collection<String>> headers, boolean required, String stubs) {
this.path = path; this.path = path;
this.loadBalancerType = loadBalancerType; this.loadBalancerType = loadBalancerType;
this.contentTypeTemplate = contentTypeTemplate; this.contentTypeTemplate = contentTypeTemplate;
@@ -96,7 +102,7 @@ public class ZookeeperDependency {
} }
/** /**
* Parsed stubs path * Parsed stubs path.
*/ */
private StubsConfiguration stubsConfiguration; private StubsConfiguration stubsConfiguration;
@@ -107,8 +113,10 @@ public class ZookeeperDependency {
} }
/** /**
* Function that will replace the placeholder {@link ZookeeperDependency#VERSION_PLACEHOLDER_REGEX} from the * Function that will replace the placeholder
* {@link ZookeeperDependency#contentTypeTemplate} with value from {@link ZookeeperDependency#version}. * {@link ZookeeperDependency#VERSION_PLACEHOLDER_REGEX} from the
* {@link ZookeeperDependency#contentTypeTemplate} with value from
* {@link ZookeeperDependency#version}.
* <p/> * <p/>
* <p> * <p>
* e.g. having: * e.g. having:
@@ -117,17 +125,19 @@ public class ZookeeperDependency {
* </p> * </p>
* <p/> * <p/>
* the result of the function will be {@code 'application/vnd.some-service.v1+json'} * the result of the function will be {@code 'application/vnd.some-service.v1+json'}
*
* @return content type template with version * @return content type template with version
*/ */
public String getContentTypeWithVersion() { public String getContentTypeWithVersion() {
if (!StringUtils.hasText(this.contentTypeTemplate) || !StringUtils.hasText(this.version)) { if (!StringUtils.hasText(this.contentTypeTemplate)
|| !StringUtils.hasText(this.version)) {
return ""; return "";
} }
return this.contentTypeTemplate.replaceAll(VERSION_PLACEHOLDER_REGEX, this.version); return this.contentTypeTemplate.replaceAll(VERSION_PLACEHOLDER_REGEX,
this.version);
} }
public Map<String, Collection<String>> getUpdatedHeaders(Map<String, Collection<String>> headers) { public Map<String, Collection<String>> getUpdatedHeaders(
Map<String, Collection<String>> headers) {
Map<String, Collection<String>> newHeaders = new HashMap<>(headers); Map<String, Collection<String>> newHeaders = new HashMap<>(headers);
if (hasContentTypeTemplate()) { if (hasContentTypeTemplate()) {
setContentTypeFromTemplate(newHeaders); setContentTypeFromTemplate(newHeaders);
@@ -142,7 +152,8 @@ public class ZookeeperDependency {
Collection<String> contentTypes = headers.get(CONTENT_TYPE_HEADER); Collection<String> contentTypes = headers.get(CONTENT_TYPE_HEADER);
if (contentTypes == null || contentTypes.isEmpty()) { if (contentTypes == null || contentTypes.isEmpty()) {
headers.put(CONTENT_TYPE_HEADER, singletonList(getContentTypeWithVersion())); headers.put(CONTENT_TYPE_HEADER, singletonList(getContentTypeWithVersion()));
} else { }
else {
contentTypes.add(getContentTypeWithVersion()); contentTypes.add(getContentTypeWithVersion());
} }
} }
@@ -152,7 +163,8 @@ public class ZookeeperDependency {
Collection<String> value = newHeaders.get(entry.getKey()); Collection<String> value = newHeaders.get(entry.getKey());
if (value == null || value.isEmpty()) { if (value == null || value.isEmpty()) {
newHeaders.put(entry.getKey(), entry.getValue()); newHeaders.put(entry.getKey(), entry.getValue());
} else { }
else {
value.addAll(entry.getValue()); value.addAll(entry.getValue());
} }
} }
@@ -235,7 +247,8 @@ public class ZookeeperDependency {
final StringBuffer sb = new StringBuffer("ZookeeperDependency{"); final StringBuffer sb = new StringBuffer("ZookeeperDependency{");
sb.append("path='").append(this.path).append('\''); sb.append("path='").append(this.path).append('\'');
sb.append(", loadBalancerType=").append(this.loadBalancerType); sb.append(", loadBalancerType=").append(this.loadBalancerType);
sb.append(", contentTypeTemplate='").append(this.contentTypeTemplate).append('\''); sb.append(", contentTypeTemplate='").append(this.contentTypeTemplate)
.append('\'');
sb.append(", version='").append(this.version).append('\''); sb.append(", version='").append(this.version).append('\'');
sb.append(", headers=").append(this.headers); sb.append(", headers=").append(this.headers);
sb.append(", required=").append(this.required); sb.append(", required=").append(this.required);
@@ -244,4 +257,5 @@ public class ZookeeperDependency {
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
import java.io.IOException; import java.io.IOException;
@@ -22,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.curator.x.discovery.ServiceCache; import org.apache.curator.x.discovery.ServiceCache;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance; import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies; import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
@@ -31,28 +33,33 @@ import org.springframework.context.ApplicationListener;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* This Dependency Watcher will verify the presence of dependencies upon startup and registers listeners * This Dependency Watcher will verify the presence of dependencies upon startup and
* to changing of state of dependencies during the application's lifecycle. * registers listeners to changing of state of dependencies during the application's
* lifecycle.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @author Michal Chmielarz, 4financeIT * @author Michal Chmielarz, 4financeIT
* @since 1.0.0 * @since 1.0.0
*
* @see DependencyPresenceOnStartupVerifier * @see DependencyPresenceOnStartupVerifier
* @see DependencyWatcherListener * @see DependencyWatcherListener
*/ */
public class DefaultDependencyWatcher implements DependencyRegistrationHookProvider, ApplicationListener<InstanceRegisteredEvent<?>> { public class DefaultDependencyWatcher implements DependencyRegistrationHookProvider,
ApplicationListener<InstanceRegisteredEvent<?>> {
private final Map<String, ServiceCache<?>> dependencyRegistry = new ConcurrentHashMap<>(); private final Map<String, ServiceCache<?>> dependencyRegistry = new ConcurrentHashMap<>();
private final List<DependencyWatcherListener> listeners; private final List<DependencyWatcherListener> listeners;
private ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
private final DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier; private final DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier;
private final ZookeeperDependencies zookeeperDependencies; private final ZookeeperDependencies zookeeperDependencies;
public DefaultDependencyWatcher(ServiceDiscovery<ZookeeperInstance> serviceDiscovery, public DefaultDependencyWatcher(ServiceDiscovery<ZookeeperInstance> serviceDiscovery,
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier, DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
List<DependencyWatcherListener> dependencyWatcherListeners, List<DependencyWatcherListener> dependencyWatcherListeners,
ZookeeperDependencies zookeeperDependencies) { ZookeeperDependencies zookeeperDependencies) {
this.serviceDiscovery = serviceDiscovery; this.serviceDiscovery = serviceDiscovery;
this.dependencyPresenceOnStartupVerifier = dependencyPresenceOnStartupVerifier; this.dependencyPresenceOnStartupVerifier = dependencyPresenceOnStartupVerifier;
this.listeners = dependencyWatcherListeners; this.listeners = dependencyWatcherListeners;
@@ -66,19 +73,22 @@ public class DefaultDependencyWatcher implements DependencyRegistrationHookProvi
@Override @Override
public void registerDependencyRegistrationHooks() { public void registerDependencyRegistrationHooks() {
for (ZookeeperDependency zookeeperDependency : this.zookeeperDependencies.getDependencyConfigurations()) { for (ZookeeperDependency zookeeperDependency : this.zookeeperDependencies
.getDependencyConfigurations()) {
String dependencyPath = zookeeperDependency.getPath(); String dependencyPath = zookeeperDependency.getPath();
ServiceCache<?> serviceCache = getServiceDiscovery() ServiceCache<?> serviceCache = getServiceDiscovery().serviceCacheBuilder()
.serviceCacheBuilder().name(dependencyPath).build(); .name(dependencyPath).build();
try { try {
serviceCache.start(); serviceCache.start();
} }
catch (Exception e) { catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e); ReflectionUtils.rethrowRuntimeException(e);
} }
this.dependencyPresenceOnStartupVerifier.verifyDependencyPresence(dependencyPath, serviceCache, zookeeperDependency.isRequired()); this.dependencyPresenceOnStartupVerifier.verifyDependencyPresence(
dependencyPath, serviceCache, zookeeperDependency.isRequired());
this.dependencyRegistry.put(dependencyPath, serviceCache); this.dependencyRegistry.put(dependencyPath, serviceCache);
serviceCache.addListener(new DependencyStateChangeListenerRegistry(this.listeners, dependencyPath, serviceCache)); serviceCache.addListener(new DependencyStateChangeListenerRegistry(
this.listeners, dependencyPath, serviceCache));
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
import java.io.IOException; import java.io.IOException;
/** /**
* Implementations of this interface are required to register dependency registration hooks * Implementations of this interface are required to register dependency registration
* on startup and their cleaning upon application context shutdown. * hooks on startup and their cleaning upon application context shutdown.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -27,16 +28,14 @@ import java.io.IOException;
public interface DependencyRegistrationHookProvider { public interface DependencyRegistrationHookProvider {
/** /**
* Register hooks upon dependencies registration * Register hooks upon dependencies registration.
* * @throws Exception if registration fails.
* @throws Exception
*/ */
void registerDependencyRegistrationHooks() throws Exception; void registerDependencyRegistrationHooks() throws Exception;
/** /**
* Unregister hooks upon dependencies registration * Unregister hooks upon dependencies registration.
* * @throws IOException if clearing fails.
* @throws IOException
*/ */
void clearDependencyRegistrationHooks() throws IOException; void clearDependencyRegistrationHooks() throws IOException;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,16 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
/** /**
* * Represents a dependency's Zookeeper connection state.
* Represents a dependency's Zookeeper connection state
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*/ */
public enum DependencyState { public enum DependencyState {
CONNECTED,
DISCONNECTED /**
* valid states.
*/
CONNECTED, DISCONNECTED
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
import java.util.List; import java.util.List;
@@ -25,7 +26,7 @@ import org.apache.curator.x.discovery.ServiceCache;
import org.apache.curator.x.discovery.details.ServiceCacheListener; import org.apache.curator.x.discovery.details.ServiceCacheListener;
/** /**
* Informs all the DependencyWatcherListeners that a dependency's state has changed * Informs all the DependencyWatcherListeners that a dependency's state has changed.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @author Tomasz Nurkiewicz, 4financeIT * @author Tomasz Nurkiewicz, 4financeIT
@@ -33,13 +34,18 @@ import org.apache.curator.x.discovery.details.ServiceCacheListener;
*/ */
public class DependencyStateChangeListenerRegistry implements ServiceCacheListener { public class DependencyStateChangeListenerRegistry implements ServiceCacheListener {
private static final Log log = LogFactory.getLog(DependencyStateChangeListenerRegistry.class); private static final Log log = LogFactory
.getLog(DependencyStateChangeListenerRegistry.class);
private final List<DependencyWatcherListener> listeners; private final List<DependencyWatcherListener> listeners;
private final String dependencyName; private final String dependencyName;
private final ServiceCache<?> serviceCache; private final ServiceCache<?> serviceCache;
public DependencyStateChangeListenerRegistry(List<DependencyWatcherListener> listeners, String dependencyName, ServiceCache<?> serviceCache) { public DependencyStateChangeListenerRegistry(
List<DependencyWatcherListener> listeners, String dependencyName,
ServiceCache<?> serviceCache) {
this.listeners = listeners; this.listeners = listeners;
this.dependencyName = dependencyName; this.dependencyName = dependencyName;
this.serviceCache = serviceCache; this.serviceCache = serviceCache;
@@ -47,13 +53,15 @@ public class DependencyStateChangeListenerRegistry implements ServiceCacheListen
@Override @Override
public void cacheChanged() { public void cacheChanged() {
DependencyState state = this.serviceCache.getInstances().isEmpty() ? DependencyState.DISCONNECTED : DependencyState.CONNECTED; DependencyState state = this.serviceCache.getInstances().isEmpty()
? DependencyState.DISCONNECTED : DependencyState.CONNECTED;
logCurrentState(state); logCurrentState(state);
informListeners(state); informListeners(state);
} }
private void logCurrentState(DependencyState dependencyState) { private void logCurrentState(DependencyState dependencyState) {
log.info("Service cache state change for '"+this.dependencyName+"' instances, current service state: " + dependencyState); log.info("Service cache state change for '" + this.dependencyName
+ "' instances, current service state: " + dependencyState);
} }
private void informListeners(DependencyState state) { private void informListeners(DependencyState state) {
@@ -66,4 +74,5 @@ public class DependencyStateChangeListenerRegistry implements ServiceCacheListen
public void stateChanged(CuratorFramework client, ConnectionState newState) { public void stateChanged(CuratorFramework client, ConnectionState newState) {
// TODO do something or ignore for what is worth // TODO do something or ignore for what is worth
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -34,12 +36,11 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
/** /**
* Provides hooks for observing dependency lifecycle in Zookeeper. * Provides hooks for observing dependency lifecycle in Zookeeper. Needs custom
* Needs custom dependencies to be set in order to work. * dependencies to be set in order to work.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*
* @see ZookeeperDependencies * @see ZookeeperDependencies
*/ */
@Configuration @Configuration
@@ -65,8 +66,8 @@ public class DependencyWatcherAutoConfiguration {
DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier, DependencyPresenceOnStartupVerifier dependencyPresenceOnStartupVerifier,
ZookeeperDependencies zookeeperDependencies) { ZookeeperDependencies zookeeperDependencies) {
return new DefaultDependencyWatcher(serviceDiscovery, return new DefaultDependencyWatcher(serviceDiscovery,
dependencyPresenceOnStartupVerifier, dependencyPresenceOnStartupVerifier, this.dependencyWatcherListeners,
this.dependencyWatcherListeners,
zookeeperDependencies); zookeeperDependencies);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,24 +13,24 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher; package org.springframework.cloud.zookeeper.discovery.watcher;
/** /**
* Performs logic upon change of state of a dependency {@link DependencyState} * Performs logic upon change of state of a dependency {@link DependencyState} in the
* in the service discovery system. * service discovery system.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
*
* @see org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies * @see org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies
*/ */
public interface DependencyWatcherListener { public interface DependencyWatcherListener {
/** /**
* Method executed upon state change of a dependency * Method executed upon state change of a dependency.
*
* @param dependencyName - alias from microservice configuration * @param dependencyName - alias from microservice configuration
* @param newState - new state of the dependency * @param newState - new state of the dependency
*/ */
void stateChanged(String dependencyName, DependencyState newState); void stateChanged(String dependencyName, DependencyState newState);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,19 +13,22 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
/** /**
* By default passes logging dependency checker in order not to shutdown the application * By default passes logging dependency checker in order not to shutdown the application
* if dependency is missing * if dependency is missing.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @version 1.0.0
*
* @see LogMissingDependencyChecker * @see LogMissingDependencyChecker
* @version 1.0.0
*/ */
public class DefaultDependencyPresenceOnStartupVerifier extends DependencyPresenceOnStartupVerifier { public class DefaultDependencyPresenceOnStartupVerifier
extends DependencyPresenceOnStartupVerifier {
public DefaultDependencyPresenceOnStartupVerifier() { public DefaultDependencyPresenceOnStartupVerifier() {
super(new LogMissingDependencyChecker()); super(new LogMissingDependencyChecker());
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,37 +13,45 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
import org.apache.curator.x.discovery.ServiceCache; import org.apache.curator.x.discovery.ServiceCache;
/** /**
* Verifier that checks for presence of mandatory dependencies and delegates to an optional * Verifier that checks for presence of mandatory dependencies and delegates to an
* presence checker verification of presence of optional dependencies. * optional presence checker verification of presence of optional dependencies.
* *
* The default implementation of required dependencies will result in shutting down of the application * The default implementation of required dependencies will result in shutting down of the
* if the dependency is missing. * application if the dependency is missing.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @author Tomasz Szymanski, 4financeIT * @author Tomasz Szymanski, 4financeIT
* @version 1.0.0
*
* @see FailOnMissingDependencyChecker * @see FailOnMissingDependencyChecker
* @version 1.0.0
*/ */
public abstract class DependencyPresenceOnStartupVerifier { public abstract class DependencyPresenceOnStartupVerifier {
private static final PresenceChecker MANDATORY_DEPENDENCY_CHECKER = new FailOnMissingDependencyChecker(); private static final PresenceChecker MANDATORY_DEPENDENCY_CHECKER = new FailOnMissingDependencyChecker();
private final PresenceChecker optionalDependencyChecker; private final PresenceChecker optionalDependencyChecker;
public DependencyPresenceOnStartupVerifier(PresenceChecker optionalDependencyChecker) { public DependencyPresenceOnStartupVerifier(
PresenceChecker optionalDependencyChecker) {
this.optionalDependencyChecker = optionalDependencyChecker; this.optionalDependencyChecker = optionalDependencyChecker;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void verifyDependencyPresence(String dependencyName, @SuppressWarnings("rawtypes") ServiceCache serviceCache, boolean required) { public void verifyDependencyPresence(String dependencyName,
@SuppressWarnings("rawtypes") ServiceCache serviceCache, boolean required) {
if (required) { if (required) {
MANDATORY_DEPENDENCY_CHECKER.checkPresence(dependencyName, serviceCache.getInstances()); MANDATORY_DEPENDENCY_CHECKER.checkPresence(dependencyName,
} else { serviceCache.getInstances());
this.optionalDependencyChecker.checkPresence(dependencyName, serviceCache.getInstances()); }
else {
this.optionalDependencyChecker.checkPresence(dependencyName,
serviceCache.getInstances());
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
import java.util.List; import java.util.List;
@@ -20,15 +21,18 @@ import java.util.List;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
/** /**
* Will result in throwing an exception if there are no running instances of the dependency * Will result in throwing an exception if there are no running instances of the
* dependency.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @author Adam Chudzik, 4financeIT * @author Adam Chudzik, 4financeIT
* @since 1.0.0 * @since 1.0.0
*/ */
public class FailOnMissingDependencyChecker implements PresenceChecker { public class FailOnMissingDependencyChecker implements PresenceChecker {
@Override @Override
public void checkPresence(String dependencyName, List<ServiceInstance<?>> serviceInstances) { public void checkPresence(String dependencyName,
List<ServiceInstance<?>> serviceInstances) {
if (serviceInstances.isEmpty()) { if (serviceInstances.isEmpty()) {
throw new NoInstancesRunningException(dependencyName); throw new NoInstancesRunningException(dependencyName);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
import java.util.List; import java.util.List;
@@ -22,7 +23,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
/** /**
* Will log the missing microservice dependency * Will log the missing microservice dependency.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @author Tomasz Dziurko, 4financeIT * @author Tomasz Dziurko, 4financeIT
@@ -33,7 +34,8 @@ public class LogMissingDependencyChecker implements PresenceChecker {
private static final Log log = LogFactory.getLog(LogMissingDependencyChecker.class); private static final Log log = LogFactory.getLog(LogMissingDependencyChecker.class);
@Override @Override
public void checkPresence(String dependencyName, List<ServiceInstance<?>> serviceInstances) { public void checkPresence(String dependencyName,
List<ServiceInstance<?>> serviceInstances) {
if (serviceInstances.isEmpty()) { if (serviceInstances.isEmpty()) {
log.warn("Microservice dependency with name [" + dependencyName log.warn("Microservice dependency with name [" + dependencyName
+ "] is missing."); + "] is missing.");

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
/** /**
@@ -20,7 +21,10 @@ package org.springframework.cloud.zookeeper.discovery.watcher.presence;
* @since 1.0.0 * @since 1.0.0
*/ */
public class NoInstancesRunningException extends RuntimeException { public class NoInstancesRunningException extends RuntimeException {
public NoInstancesRunningException(String dependencyName) { public NoInstancesRunningException(String dependencyName) {
super("Required microservice dependency with name [" + dependencyName + "] is missing"); super("Required microservice dependency with name [" + dependencyName
+ "] is missing");
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery.watcher.presence; package org.springframework.cloud.zookeeper.discovery.watcher.presence;
import java.util.List; import java.util.List;
@@ -20,8 +21,8 @@ import java.util.List;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
/** /**
* The implementation of this interface will be called upon checking if a dependency with a given name * The implementation of this interface will be called upon checking if a dependency with
* is present upon startup within the provided service instances. * a given name is present upon startup within the provided service instances.
* *
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
* @since 1.0.0 * @since 1.0.0
@@ -29,10 +30,10 @@ import org.apache.curator.x.discovery.ServiceInstance;
public interface PresenceChecker { public interface PresenceChecker {
/** /**
* Checks if a given dependency is present * Checks if a given dependency is present.
* * @param dependencyName Name of the dependency.
* @param dependencyName * @param serviceInstances - instances to check the dependency for.
* @param serviceInstances - instances to check the dependency for
*/ */
void checkPresence(String dependencyName, List<ServiceInstance<?>> serviceInstances); void checkPresence(String dependencyName, List<ServiceInstance<?>> serviceInstances);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,22 +16,23 @@
package org.springframework.cloud.zookeeper.serviceregistry; package org.springframework.cloud.zookeeper.serviceregistry;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.apache.curator.x.discovery.ServiceType;
import org.apache.curator.x.discovery.UriSpec;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import java.net.URI; import java.net.URI;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.apache.curator.x.discovery.ServiceType;
import org.apache.curator.x.discovery.UriSpec;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import static org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties.DEFAULT_URI_SPEC; import static org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties.DEFAULT_URI_SPEC;
/** /**
* {@link org.springframework.cloud.client.serviceregistry.Registration} that lazily builds * {@link org.springframework.cloud.client.serviceregistry.Registration} that lazily
* a {@link ServiceInstance} so the port can by dynamically set (for instance, when the * builds a {@link ServiceInstance} so the port can by dynamically set (for instance, when
* user wants a dynamic port for spring boot. * the user wants a dynamic port for spring boot.
* *
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@@ -40,86 +41,23 @@ public class ServiceInstanceRegistration implements ZookeeperRegistration {
public static RegistrationBuilder builder() { public static RegistrationBuilder builder() {
try { try {
return new RegistrationBuilder(ServiceInstance.<ZookeeperInstance>builder()); return new RegistrationBuilder(ServiceInstance.<ZookeeperInstance>builder());
} catch (Exception e) { }
catch (Exception e) {
throw new RuntimeException("Error creating ServiceInstanceBuilder", e); throw new RuntimeException("Error creating ServiceInstanceBuilder", e);
} }
} }
public static RegistrationBuilder builder(ServiceInstanceBuilder<ZookeeperInstance> builder) { public static RegistrationBuilder builder(
ServiceInstanceBuilder<ZookeeperInstance> builder) {
return new RegistrationBuilder(builder); return new RegistrationBuilder(builder);
} }
public static class RegistrationBuilder {
protected ServiceInstanceBuilder<ZookeeperInstance> builder;
public RegistrationBuilder(ServiceInstanceBuilder<ZookeeperInstance> builder) {
this.builder = builder;
}
public ServiceInstanceRegistration build() {
return new ServiceInstanceRegistration(this.builder);
}
public RegistrationBuilder name(String name) {
this.builder.name(name);
return this;
}
public RegistrationBuilder address(String address) {
this.builder.address(address);
return this;
}
public RegistrationBuilder id(String id) {
this.builder.id(id);
return this;
}
public RegistrationBuilder port(int port) {
this.builder.port(port);
return this;
}
public RegistrationBuilder sslPort(int port) {
this.builder.sslPort(port);
return this;
}
public RegistrationBuilder payload(ZookeeperInstance payload) {
this.builder.payload(payload);
return this;
}
public RegistrationBuilder serviceType(ServiceType serviceType) {
this.builder.serviceType(serviceType);
return this;
}
public RegistrationBuilder registrationTimeUTC(long registrationTimeUTC) {
this.builder.registrationTimeUTC(registrationTimeUTC);
return this;
}
public RegistrationBuilder uriSpec(UriSpec uriSpec) {
this.builder.uriSpec(uriSpec);
return this;
}
public RegistrationBuilder uriSpec(String uriSpec) {
this.builder.uriSpec(new UriSpec(uriSpec));
return this;
}
public RegistrationBuilder defaultUriSpec() {
this.builder.uriSpec(new UriSpec(DEFAULT_URI_SPEC));
return this;
}
}
protected ServiceInstance<ZookeeperInstance> serviceInstance; protected ServiceInstance<ZookeeperInstance> serviceInstance;
protected ServiceInstanceBuilder<ZookeeperInstance> builder; protected ServiceInstanceBuilder<ZookeeperInstance> builder;
public ServiceInstanceRegistration(ServiceInstanceBuilder<ZookeeperInstance> builder) { public ServiceInstanceRegistration(
ServiceInstanceBuilder<ZookeeperInstance> builder) {
this.builder = builder; this.builder = builder;
} }
@@ -185,4 +123,77 @@ public class ServiceInstanceRegistration implements ZookeeperRegistration {
} }
return this.serviceInstance.getPayload().getMetadata(); return this.serviceInstance.getPayload().getMetadata();
} }
/**
* A builder for ServiceInstanceRegistration.
*/
public static class RegistrationBuilder {
protected ServiceInstanceBuilder<ZookeeperInstance> builder;
public RegistrationBuilder(ServiceInstanceBuilder<ZookeeperInstance> builder) {
this.builder = builder;
}
public ServiceInstanceRegistration build() {
return new ServiceInstanceRegistration(this.builder);
}
public RegistrationBuilder name(String name) {
this.builder.name(name);
return this;
}
public RegistrationBuilder address(String address) {
this.builder.address(address);
return this;
}
public RegistrationBuilder id(String id) {
this.builder.id(id);
return this;
}
public RegistrationBuilder port(int port) {
this.builder.port(port);
return this;
}
public RegistrationBuilder sslPort(int port) {
this.builder.sslPort(port);
return this;
}
public RegistrationBuilder payload(ZookeeperInstance payload) {
this.builder.payload(payload);
return this;
}
public RegistrationBuilder serviceType(ServiceType serviceType) {
this.builder.serviceType(serviceType);
return this;
}
public RegistrationBuilder registrationTimeUTC(long registrationTimeUTC) {
this.builder.registrationTimeUTC(registrationTimeUTC);
return this;
}
public RegistrationBuilder uriSpec(UriSpec uriSpec) {
this.builder.uriSpec(uriSpec);
return this;
}
public RegistrationBuilder uriSpec(String uriSpec) {
this.builder.uriSpec(new UriSpec(uriSpec));
return this;
}
public RegistrationBuilder defaultUriSpec() {
this.builder.uriSpec(new UriSpec(DEFAULT_URI_SPEC));
return this;
}
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,34 +18,36 @@ package org.springframework.cloud.zookeeper.serviceregistry;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
/** /**
* Zookeeper {@link AbstractAutoServiceRegistration} * Zookeeper {@link AbstractAutoServiceRegistration} that uses
* that uses {@link ZookeeperServiceRegistry} to register and de-register instances. * {@link ZookeeperServiceRegistry} to register and de-register instances.
* *
* @author Spencer Gibb * @author Spencer Gibb
* @since 1.0.0 * @since 1.0.0
*/ */
public class ZookeeperAutoServiceRegistration extends AbstractAutoServiceRegistration<ZookeeperRegistration> { public class ZookeeperAutoServiceRegistration
extends AbstractAutoServiceRegistration<ZookeeperRegistration> {
private static final Log log = LogFactory.getLog(ZookeeperAutoServiceRegistration.class); private static final Log log = LogFactory
.getLog(ZookeeperAutoServiceRegistration.class);
private ZookeeperRegistration registration; private ZookeeperRegistration registration;
private ZookeeperDiscoveryProperties properties; private ZookeeperDiscoveryProperties properties;
public ZookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry, public ZookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry,
ZookeeperRegistration registration, ZookeeperRegistration registration, ZookeeperDiscoveryProperties properties) {
ZookeeperDiscoveryProperties properties) {
this(registry, registration, properties, null); this(registry, registration, properties, null);
} }
public ZookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry, public ZookeeperAutoServiceRegistration(ZookeeperServiceRegistry registry,
ZookeeperRegistration registration, ZookeeperRegistration registration, ZookeeperDiscoveryProperties properties,
ZookeeperDiscoveryProperties properties, AutoServiceRegistrationProperties arProperties) {
AutoServiceRegistrationProperties arProperties) {
super(registry, arProperties); super(registry, arProperties);
this.registration = registration; this.registration = registration;
this.properties = properties; this.properties = properties;
@@ -93,4 +95,5 @@ public class ZookeeperAutoServiceRegistration extends AbstractAutoServiceRegistr
protected Object getConfiguration() { protected Object getConfiguration() {
return this.properties; return this.properties;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -38,8 +38,9 @@ import org.springframework.util.StringUtils;
@ConditionalOnMissingBean(type = "org.springframework.cloud.zookeeper.discovery.ZookeeperLifecycle") @ConditionalOnMissingBean(type = "org.springframework.cloud.zookeeper.discovery.ZookeeperLifecycle")
@ConditionalOnZookeeperDiscoveryEnabled @ConditionalOnZookeeperDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter( { ZookeeperServiceRegistryAutoConfiguration.class} ) @AutoConfigureAfter({ ZookeeperServiceRegistryAutoConfiguration.class })
@AutoConfigureBefore( {AutoServiceRegistrationAutoConfiguration.class,ZookeeperDiscoveryAutoConfiguration.class} ) @AutoConfigureBefore({ AutoServiceRegistrationAutoConfiguration.class,
ZookeeperDiscoveryAutoConfiguration.class })
public class ZookeeperAutoServiceRegistrationAutoConfiguration { public class ZookeeperAutoServiceRegistrationAutoConfiguration {
@Bean @Bean
@@ -73,7 +74,6 @@ public class ZookeeperAutoServiceRegistrationAutoConfiguration {
builder.id(properties.getInstanceId()); builder.id(properties.getInstanceId());
} }
// TODO add customizer? // TODO add customizer?
return builder.build(); return builder.build();

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.cloud.zookeeper.serviceregistry; package org.springframework.cloud.zookeeper.serviceregistry;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance; import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
@@ -28,4 +29,5 @@ public interface ZookeeperRegistration extends Registration {
ServiceInstance<ZookeeperInstance> getServiceInstance(); ServiceInstance<ZookeeperInstance> getServiceInstance();
void setPort(int port); void setPort(int port);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import java.io.IOException;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
@@ -36,8 +37,8 @@ import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegistration>, SmartInitializingSingleton, public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegistration>,
Closeable { SmartInitializingSingleton, Closeable {
// private AtomicBoolean started = new AtomicBoolean(); // private AtomicBoolean started = new AtomicBoolean();
@@ -48,24 +49,28 @@ public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegist
// protected InstanceSerializer<ZookeeperInstance> instanceSerializer; // protected InstanceSerializer<ZookeeperInstance> instanceSerializer;
private ServiceDiscovery<ZookeeperInstance> serviceDiscovery; private ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
public ZookeeperServiceRegistry(ServiceDiscovery<ZookeeperInstance> serviceDiscovery) { public ZookeeperServiceRegistry(
ServiceDiscovery<ZookeeperInstance> serviceDiscovery) {
this.serviceDiscovery = serviceDiscovery; this.serviceDiscovery = serviceDiscovery;
} }
/** /**
* TODO: add when ZookeeperServiceDiscovery is removed * TODO: add when ZookeeperServiceDiscovery is removed One can override this method to
* One can override this method to provide custom way of registering {@link ServiceDiscovery} * provide custom way of registering {@link ServiceDiscovery}
*/
/*
* private void configureServiceDiscovery() {
* this.zookeeperServiceDiscovery.configureServiceDiscovery(this.
* zookeeperServiceDiscovery.getServiceDiscoveryRef(), this.curator, this.properties,
* this.instanceSerializer, this.zookeeperServiceDiscovery.getServiceInstanceRef()); }
*/ */
/*private void configureServiceDiscovery() {
this.zookeeperServiceDiscovery.configureServiceDiscovery(this.zookeeperServiceDiscovery.getServiceDiscoveryRef(),
this.curator, this.properties, this.instanceSerializer, this.zookeeperServiceDiscovery.getServiceInstanceRef());
}*/
@Override @Override
public void register(ZookeeperRegistration registration) { public void register(ZookeeperRegistration registration) {
try { try {
getServiceDiscovery().registerService(registration.getServiceInstance()); getServiceDiscovery().registerService(registration.getServiceInstance());
} catch (Exception e) { }
catch (Exception e) {
rethrowRuntimeException(e); rethrowRuntimeException(e);
} }
} }
@@ -78,7 +83,8 @@ public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegist
public void deregister(ZookeeperRegistration registration) { public void deregister(ZookeeperRegistration registration) {
try { try {
getServiceDiscovery().unregisterService(registration.getServiceInstance()); getServiceDiscovery().unregisterService(registration.getServiceInstance());
} catch (Exception e) { }
catch (Exception e) {
rethrowRuntimeException(e); rethrowRuntimeException(e);
} }
} }
@@ -87,7 +93,8 @@ public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegist
public void afterSingletonsInstantiated() { public void afterSingletonsInstantiated() {
try { try {
getServiceDiscovery().start(); getServiceDiscovery().start();
} catch (Exception e) { }
catch (Exception e) {
rethrowRuntimeException(e); rethrowRuntimeException(e);
} }
} }
@@ -96,19 +103,22 @@ public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegist
public void close() { public void close() {
try { try {
getServiceDiscovery().close(); getServiceDiscovery().close();
} catch (IOException e) { }
catch (IOException e) {
rethrowRuntimeException(e); rethrowRuntimeException(e);
} }
} }
@Override @Override
public void setStatus(ZookeeperRegistration registration, String status) { public void setStatus(ZookeeperRegistration registration, String status) {
ServiceInstance<ZookeeperInstance> serviceInstance = registration.getServiceInstance(); ServiceInstance<ZookeeperInstance> serviceInstance = registration
.getServiceInstance();
ZookeeperInstance instance = serviceInstance.getPayload(); ZookeeperInstance instance = serviceInstance.getPayload();
instance.getMetadata().put(INSTANCE_STATUS_KEY, status); instance.getMetadata().put(INSTANCE_STATUS_KEY, status);
try { try {
getServiceDiscovery().updateService(serviceInstance); getServiceDiscovery().updateService(serviceInstance);
} catch (Exception e) { }
catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e); ReflectionUtils.rethrowRuntimeException(e);
} }
} }
@@ -129,7 +139,10 @@ public class ZookeeperServiceRegistry implements ServiceRegistry<ZookeeperRegist
return this.curator; return this.curator;
} }
/*protected AtomicReference<ServiceDiscovery<ZookeeperInstance>> getServiceDiscoveryRef() { /*
return this.zookeeperServiceDiscovery.getServiceDiscoveryRef(); * protected AtomicReference<ServiceDiscovery<ZookeeperInstance>>
}*/ * getServiceDiscoveryRef() { return
* this.zookeeperServiceDiscovery.getServiceDiscoveryRef(); }
*/
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.springframework.cloud.zookeeper.serviceregistry;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.details.InstanceSerializer; import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer; import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -40,7 +41,8 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnZookeeperDiscoveryEnabled @ConditionalOnZookeeperDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.cloud.service-registry.enabled", matchIfMissing = true)
@AutoConfigureBefore(ServiceRegistryAutoConfiguration.class) @AutoConfigureBefore(ServiceRegistryAutoConfiguration.class)
public class ZookeeperServiceRegistryAutoConfiguration implements ApplicationContextAware { public class ZookeeperServiceRegistryAutoConfiguration
implements ApplicationContextAware {
private ApplicationContext context; private ApplicationContext context;
@@ -63,7 +65,9 @@ public class ZookeeperServiceRegistryAutoConfiguration implements ApplicationCon
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(InetUtils inetUtils) { public ZookeeperDiscoveryProperties zookeeperDiscoveryProperties(
InetUtils inetUtils) {
return new ZookeeperDiscoveryProperties(inetUtils); return new ZookeeperDiscoveryProperties(inetUtils);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.details.InstanceSerializer; import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.apache.curator.x.discovery.details.JsonInstanceSerializer; import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.zookeeper.discovery.ConditionalOnZookeeperDiscoveryEnabled; import org.springframework.cloud.zookeeper.discovery.ConditionalOnZookeeperDiscoveryEnabled;
@@ -58,6 +59,8 @@ public class CuratorServiceDiscoveryAutoConfiguration {
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ServiceDiscovery<ZookeeperInstance> curatorServiceDiscovery( public ServiceDiscovery<ZookeeperInstance> curatorServiceDiscovery(
ServiceDiscoveryCustomizer customizer) { ServiceDiscoveryCustomizer customizer) {
return customizer.customize(ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)); return customizer
.customize(ServiceDiscoveryBuilder.builder(ZookeeperInstance.class));
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,27 +20,32 @@ import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.apache.curator.x.discovery.details.InstanceSerializer; import org.apache.curator.x.discovery.details.InstanceSerializer;
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties; import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance; import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public class DefaultServiceDiscoveryCustomizer implements ServiceDiscoveryCustomizer{ public class DefaultServiceDiscoveryCustomizer implements ServiceDiscoveryCustomizer {
protected CuratorFramework curator; protected CuratorFramework curator;
protected ZookeeperDiscoveryProperties properties; protected ZookeeperDiscoveryProperties properties;
protected InstanceSerializer<ZookeeperInstance> instanceSerializer; protected InstanceSerializer<ZookeeperInstance> instanceSerializer;
public DefaultServiceDiscoveryCustomizer(CuratorFramework curator, ZookeeperDiscoveryProperties properties, InstanceSerializer<ZookeeperInstance> instanceSerializer) { public DefaultServiceDiscoveryCustomizer(CuratorFramework curator,
ZookeeperDiscoveryProperties properties,
InstanceSerializer<ZookeeperInstance> instanceSerializer) {
this.curator = curator; this.curator = curator;
this.properties = properties; this.properties = properties;
this.instanceSerializer = instanceSerializer; this.instanceSerializer = instanceSerializer;
} }
@Override @Override
public ServiceDiscovery<ZookeeperInstance> customize(ServiceDiscoveryBuilder<ZookeeperInstance> builder) { public ServiceDiscovery<ZookeeperInstance> customize(
ServiceDiscoveryBuilder<ZookeeperInstance> builder) {
// @formatter:off // @formatter:off
return builder return builder
.client(this.curator) .client(this.curator)
@@ -49,4 +54,5 @@ public class DefaultServiceDiscoveryCustomizer implements ServiceDiscoveryCustom
.build(); .build();
// @formatter:on // @formatter:on
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.cloud.zookeeper.support;
import org.apache.curator.x.discovery.ServiceDiscovery; import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance; import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
/** /**
@@ -25,5 +26,7 @@ import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
*/ */
public interface ServiceDiscoveryCustomizer { public interface ServiceDiscoveryCustomizer {
ServiceDiscovery<ZookeeperInstance> customize(ServiceDiscoveryBuilder<ZookeeperInstance> builder); ServiceDiscovery<ZookeeperInstance> customize(
ServiceDiscoveryBuilder<ZookeeperInstance> builder);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,22 +16,31 @@
package org.springframework.cloud.zookeeper.support; package org.springframework.cloud.zookeeper.support;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
public interface StatusConstants { public final class StatusConstants {
private StatusConstants() {
}
/** /**
* Key to the {@link org.springframework.cloud.zookeeper.discovery.ZookeeperInstance#metadata} map. * Key to the
* {@link ZookeeperInstance#getMetadata()}
* map.
*/ */
String INSTANCE_STATUS_KEY = "instance_status"; public static final String INSTANCE_STATUS_KEY = "instance_status";
/** /**
* UP value for {@link StatusConstants#INSTANCE_STATUS_KEY} key. * UP value for {@link StatusConstants#INSTANCE_STATUS_KEY} key.
*/ */
String STATUS_UP = "UP"; public static final String STATUS_UP = "UP";
/** /**
* OUT_OF_SERVICE value for {@link StatusConstants#INSTANCE_STATUS_KEY} key. * OUT_OF_SERVICE value for {@link StatusConstants#INSTANCE_STATUS_KEY} key.
*/ */
String STATUS_OUT_OF_SERVICE = "OUT_OF_SERVICE"; public static final String STATUS_OUT_OF_SERVICE = "OUT_OF_SERVICE";
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance; import org.apache.curator.x.discovery.ServiceInstance;
import org.assertj.core.data.MapEntry; import org.assertj.core.data.MapEntry;
import org.junit.Test; import org.junit.Test;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance; import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServer; import org.springframework.cloud.zookeeper.discovery.ZookeeperServer;
import org.springframework.cloud.zookeeper.discovery.ZookeeperServerList; import org.springframework.cloud.zookeeper.discovery.ZookeeperServerList;
@@ -52,7 +53,8 @@ public class ZookeeperServerListTests {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testEmptyInstancesReturnsEmptyList() throws Exception { public void testEmptyInstancesReturnsEmptyList() throws Exception {
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
ServiceDiscovery.class);
when(serviceDiscovery.queryForInstances(anyString())).thenReturn(null); when(serviceDiscovery.queryForInstances(anyString())).thenReturn(null);
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery); ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
@@ -66,27 +68,31 @@ public class ZookeeperServerListTests {
ArrayList<ServiceInstance<ZookeeperInstance>> instances = new ArrayList<>(); ArrayList<ServiceInstance<ZookeeperInstance>> instances = new ArrayList<>();
instances.add(serviceInstance(1, null)); instances.add(serviceInstance(1, null));
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
when(serviceDiscovery.queryForInstances(nullable(String.class))).thenReturn(instances); ServiceDiscovery.class);
when(serviceDiscovery.queryForInstances(nullable(String.class)))
.thenReturn(instances);
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery); ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
List<ZookeeperServer> servers = serverList.getInitialListOfServers(); List<ZookeeperServer> servers = serverList.getInitialListOfServers();
assertThat(servers).hasSize(1); assertThat(servers).hasSize(1);
} }
private ServiceInstance<ZookeeperInstance> serviceInstance(int instanceNum, String instanceStatus) { private ServiceInstance<ZookeeperInstance> serviceInstance(int instanceNum,
String instanceStatus) {
String id = "instance" + instanceNum + "id"; String id = "instance" + instanceNum + "id";
String name = "instance" + instanceNum + "name"; String name = "instance" + instanceNum + "name";
ZookeeperInstance payload = null; ZookeeperInstance payload = null;
if (instanceStatus != null) { if (instanceStatus != null) {
payload = new ZookeeperInstance(id, name, Collections.singletonMap(INSTANCE_STATUS_KEY, instanceStatus)); payload = new ZookeeperInstance(id, name,
Collections.singletonMap(INSTANCE_STATUS_KEY, instanceStatus));
} }
String address = "instance" + instanceNum + "addr"; String address = "instance" + instanceNum + "addr";
int port = 8080 + instanceNum; int port = 8080 + instanceNum;
return new ServiceInstance<>(name, id, address, port, null, payload, return new ServiceInstance<>(name, id, address, port, null, payload, 0, null,
0, null, null); null);
} }
@Test @Test
@@ -96,8 +102,10 @@ public class ZookeeperServerListTests {
instances.add(serviceInstance(1, STATUS_UP)); instances.add(serviceInstance(1, STATUS_UP));
instances.add(serviceInstance(2, STATUS_OUT_OF_SERVICE)); instances.add(serviceInstance(2, STATUS_OUT_OF_SERVICE));
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
when(serviceDiscovery.queryForInstances(nullable(String.class))).thenReturn(instances); ServiceDiscovery.class);
when(serviceDiscovery.queryForInstances(nullable(String.class)))
.thenReturn(instances);
ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery); ZookeeperServerList serverList = new ZookeeperServerList(serviceDiscovery);
List<ZookeeperServer> servers = serverList.getInitialListOfServers(); List<ZookeeperServer> servers = serverList.getInitialListOfServers();
@@ -106,4 +114,5 @@ public class ZookeeperServerListTests {
assertThat(servers.get(0).getInstance().getPayload().getMetadata()) assertThat(servers.get(0).getInstance().getPayload().getMetadata())
.contains(MapEntry.entry(INSTANCE_STATUS_KEY, STATUS_UP)); .contains(MapEntry.entry(INSTANCE_STATUS_KEY, STATUS_UP));
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2015 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.zookeeper.discovery; package org.springframework.cloud.zookeeper.discovery;
import java.io.IOException; import java.io.IOException;
@@ -26,7 +27,9 @@ import org.apache.curator.x.discovery.UriSpec;
public class TestServiceRegistrar { public class TestServiceRegistrar {
private final int serverPort; private final int serverPort;
private final CuratorFramework curatorFramework; private final CuratorFramework curatorFramework;
private final ServiceDiscovery serviceDiscovery; private final ServiceDiscovery serviceDiscovery;
public TestServiceRegistrar(int serverPort, CuratorFramework curatorFramework) { public TestServiceRegistrar(int serverPort, CuratorFramework curatorFramework) {
@@ -38,33 +41,29 @@ public class TestServiceRegistrar {
public void start() { public void start() {
try { try {
this.serviceDiscovery.start(); this.serviceDiscovery.start();
} catch (Exception e) { }
catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public ServiceInstance serviceInstance() { public ServiceInstance serviceInstance() {
try { try {
return ServiceInstance.builder().uriSpec(new UriSpec("{scheme}://{address}:{port}/")) return ServiceInstance.builder()
.address("localhost") .uriSpec(new UriSpec("{scheme}://{address}:{port}/"))
.port(this.serverPort) .address("localhost").port(this.serverPort).name("testInstance")
.name("testInstance")
.build(); .build();
} catch (Exception e) { }
catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public ServiceDiscovery serviceDiscovery() { public ServiceDiscovery serviceDiscovery() {
return ServiceDiscoveryBuilder return ServiceDiscoveryBuilder.builder(Void.class).basePath("/services")
.builder(Void.class) .client(this.curatorFramework).thisInstance(serviceInstance()).build();
.basePath("/services")
.client(this.curatorFramework)
.thisInstance(serviceInstance())
.build();
} }
public void stop() { public void stop() {
try { try {
this.serviceDiscovery.close(); this.serviceDiscovery.close();
@@ -73,4 +72,5 @@ public class TestServiceRegistrar {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.util.List;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -44,18 +45,22 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryAutoRegistrationFalseTests.Config.class, @SpringBootTest(classes = ZookeeperDiscoveryAutoRegistrationFalseTests.Config.class, properties = {
properties = { "spring.application.name=testzkautoregfalse", "debug=true" }, "spring.application.name=testzkautoregfalse",
webEnvironment = RANDOM_PORT) "debug=true" }, webEnvironment = RANDOM_PORT)
@DirtiesContext @DirtiesContext
public class ZookeeperDiscoveryAutoRegistrationFalseTests { public class ZookeeperDiscoveryAutoRegistrationFalseTests {
@Autowired DiscoveryClient discoveryClient; @Autowired
@Value("${spring.application.name}") String springAppName; DiscoveryClient discoveryClient;
@Test public void discovery_client_is_zookeeper() { @Value("${spring.application.name}")
//given: this.discoveryClient String springAppName;
//expect:
@Test
public void discovery_client_is_zookeeper() {
// given: this.discoveryClient
// expect:
then(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class); then(discoveryClient).isInstanceOf(CompositeDiscoveryClient.class);
CompositeDiscoveryClient composite = (CompositeDiscoveryClient) discoveryClient; CompositeDiscoveryClient composite = (CompositeDiscoveryClient) discoveryClient;
List<DiscoveryClient> discoveryClients = composite.getDiscoveryClients(); List<DiscoveryClient> discoveryClients = composite.getDiscoveryClients();
@@ -63,10 +68,12 @@ public class ZookeeperDiscoveryAutoRegistrationFalseTests {
then(first).isInstanceOf(ZookeeperDiscoveryClient.class); then(first).isInstanceOf(ZookeeperDiscoveryClient.class);
} }
@Test public void application_should_not_have_been_registered() { @Test
//given: public void application_should_not_have_been_registered() {
List<ServiceInstance> instances = this.discoveryClient.getInstances(springAppName); // given:
//expect: List<ServiceInstance> instances = this.discoveryClient
.getInstances(springAppName);
// expect:
then(instances).isEmpty(); then(instances).isEmpty();
} }
@@ -82,8 +89,11 @@ public class ZookeeperDiscoveryAutoRegistrationFalseTests {
@Profile("ribbon") @Profile("ribbon")
class PingController { class PingController {
@RequestMapping("/ping") String ping() { @RequestMapping("/ping")
String ping() {
return "pong"; return "pong";
} }
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import java.util.List; import java.util.List;
@@ -17,9 +33,11 @@ import static org.mockito.Mockito.when;
*/ */
public class ZookeeperDiscoveryClientTests { public class ZookeeperDiscoveryClientTests {
@Test public void should_return_an_empty_list_of_services_if_service_discovery_is_null() { @Test
public void should_return_an_empty_list_of_services_if_service_discovery_is_null() {
// given: // given:
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
ServiceDiscovery.class);
ZookeeperDiscoveryClient zookeeperDiscoveryClient = new ZookeeperDiscoveryClient( ZookeeperDiscoveryClient zookeeperDiscoveryClient = new ZookeeperDiscoveryClient(
serviceDiscovery, null, new ZookeeperDiscoveryProperties()); serviceDiscovery, null, new ZookeeperDiscoveryProperties());
// when: // when:
@@ -31,7 +49,8 @@ public class ZookeeperDiscoveryClientTests {
@Test @Test
public void getServicesShouldReturnEmptyWhenNoNodeException() throws Exception { public void getServicesShouldReturnEmptyWhenNoNodeException() throws Exception {
// given: // given:
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
ServiceDiscovery.class);
when(serviceDiscovery.queryForNames()).thenThrow(new NoNodeException()); when(serviceDiscovery.queryForNames()).thenThrow(new NoNodeException());
ZookeeperDiscoveryClient discoveryClient = new ZookeeperDiscoveryClient( ZookeeperDiscoveryClient discoveryClient = new ZookeeperDiscoveryClient(
serviceDiscovery, null, new ZookeeperDiscoveryProperties()); serviceDiscovery, null, new ZookeeperDiscoveryProperties());
@@ -44,8 +63,10 @@ public class ZookeeperDiscoveryClientTests {
@Test @Test
public void getInstancesshouldReturnEmptyWhenNoNodeException() throws Exception { public void getInstancesshouldReturnEmptyWhenNoNodeException() throws Exception {
// given: // given:
ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(ServiceDiscovery.class); ServiceDiscovery<ZookeeperInstance> serviceDiscovery = mock(
when(serviceDiscovery.queryForInstances("myservice")).thenThrow(new NoNodeException()); ServiceDiscovery.class);
when(serviceDiscovery.queryForInstances("myservice"))
.thenThrow(new NoNodeException());
ZookeeperDiscoveryClient discoveryClient = new ZookeeperDiscoveryClient( ZookeeperDiscoveryClient discoveryClient = new ZookeeperDiscoveryClient(
serviceDiscovery, null, new ZookeeperDiscoveryProperties()); serviceDiscovery, null, new ZookeeperDiscoveryProperties());
// when: // when:
@@ -53,4 +74,5 @@ public class ZookeeperDiscoveryClientTests {
// then: // then:
then(instances).isEmpty(); then(instances).isEmpty();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,8 +20,10 @@ import org.apache.curator.framework.CuratorFramework;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig; import org.springframework.cloud.zookeeper.discovery.test.CommonTestConfig;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -33,12 +35,13 @@ import org.springframework.test.context.junit4.SpringRunner;
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryDisabledTests.SomeApp.class, @SpringBootTest(classes = ZookeeperDiscoveryDisabledTests.SomeApp.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
properties = {"spring.cloud.zookeeper.discovery.enabled=false", "debug=true"}) "spring.cloud.zookeeper.discovery.enabled=false", "debug=true" })
public class ZookeeperDiscoveryDisabledTests { public class ZookeeperDiscoveryDisabledTests {
@Test @Test
@Ignore //FIXME 2.0.0 error creating zookeeperHealthIndicator, CuratorFramework not found, but report says it is @Ignore // FIXME 2.0.0 error creating zookeeperHealthIndicator, CuratorFramework not
// found, but report says it is
public void should_start_the_context_with_discovery_disabled() throws Exception { public void should_start_the_context_with_discovery_disabled() throws Exception {
} }
@@ -46,9 +49,12 @@ public class ZookeeperDiscoveryDisabledTests {
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(CommonTestConfig.class) @Import(CommonTestConfig.class)
static class SomeApp { static class SomeApp {
@Bean @Bean
CuratorFramework curator() { CuratorFramework curator() {
return null; return null;
} }
} }
} }

View File

@@ -1,7 +1,24 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -17,23 +34,26 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, @SpringBootTest(webEnvironment = RANDOM_PORT, properties = "management.health.zookeeper.enabled=false")
properties = "management.health.zookeeper.enabled=false")
public class ZookeeperDiscoveryHealthIndicatorDisabledTests { public class ZookeeperDiscoveryHealthIndicatorDisabledTests {
@Autowired(required = false) @Autowired(required = false)
private ZookeeperDiscoveryHealthIndicator healthIndicator; private ZookeeperDiscoveryHealthIndicator healthIndicator;
// Issue: #101 - ZookeeperDiscoveryHealthIndicator should be able to be disabled with a property // Issue: #101 - ZookeeperDiscoveryHealthIndicator should be able to be disabled with
@Test public void healthIndicatorDisabled() { // a property
@Test
public void healthIndicatorDisabled() {
// when: // when:
// then: // then:
then(this.healthIndicator).isNull(); then(this.healthIndicator).isNull();
} }
@SpringBootConfiguration @SpringBootConfiguration
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(CommonTestConfig.class) @Import(CommonTestConfig.class)
static class Config {} static class Config {
}
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
@@ -10,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -37,27 +54,32 @@ import static org.springframework.cloud.zookeeper.discovery.test.TestRibbonClien
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.Config.class, @SpringBootTest(classes = ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests.Config.class,
properties = "management.endpoints.web.exposure.include=*", properties = "management.endpoints.web.exposure.include=*", webEnvironment = RANDOM_PORT)
webEnvironment = RANDOM_PORT)
@ActiveProfiles("nestedstructure") @ActiveProfiles("nestedstructure")
public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests { public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests {
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); private static final Log log = LogFactory
.getLog(MethodHandles.lookup().lookupClass());
@Autowired TestRibbonClient testRibbonClient; @Autowired
@Autowired CuratorFramework curatorFramework; TestRibbonClient testRibbonClient;
@Autowired
CuratorFramework curatorFramework;
// Issue: #54 - ZookeeperDiscoveryHealthIndicator fails on nested structure // Issue: #54 - ZookeeperDiscoveryHealthIndicator fails on nested structure
@Test public void should_return_a_response_that_app_is_in_a_healthy_state_when_nested_folders_in_zookeeper_are_present() @Test
public void should_return_a_response_that_app_is_in_a_healthy_state_when_nested_folders_in_zookeeper_are_present()
throws Exception { throws Exception {
// when: // when:
String response = this.testRibbonClient.callService("me", BASE_PATH + "/health"); String response = this.testRibbonClient.callService("me", BASE_PATH + "/health");
// then: // then:
log.info("Received response [" + response + "]"); log.info("Received response [" + response + "]");
then(this.curatorFramework.getChildren().forPath("/services/me")).isNotEmpty(); then(this.curatorFramework.getChildren().forPath("/services/me")).isNotEmpty();
then(this.curatorFramework.getChildren().forPath("/services/a/b/c/d/anotherservice")).isNotEmpty(); then(this.curatorFramework.getChildren()
.forPath("/services/a/b/c/d/anotherservice")).isNotEmpty();
} }
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(CommonTestConfig.class) @Import(CommonTestConfig.class)
@@ -66,19 +88,18 @@ public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests {
@Autowired @Autowired
ZookeeperServiceRegistry serviceRegistry; ZookeeperServiceRegistry serviceRegistry;
private ZookeeperRegistration registration; private ZookeeperRegistration registration;
@PostConstruct @PostConstruct
void registerNestedDependency() { void registerNestedDependency() {
try { try {
this.registration = ServiceInstanceRegistration.builder() this.registration = ServiceInstanceRegistration.builder().defaultUriSpec()
.defaultUriSpec() .address("anyUrl").port(10).name("/a/b/c/d/anotherservice")
.address("anyUrl")
.port(10)
.name("/a/b/c/d/anotherservice")
.build(); .build();
this.serviceRegistry.register(registration); this.serviceRegistry.register(registration);
} catch (Exception e) { }
catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@@ -88,9 +109,12 @@ public class ZookeeperDiscoveryHealthIndicatorWithNestedStructureTests {
this.serviceRegistry.deregister(this.registration); this.serviceRegistry.deregister(this.registration);
} }
@Bean TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate, @Bean
TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,
@Value("${spring.application.name}") String springAppName) { @Value("${spring.application.name}") String springAppName) {
return new TestRibbonClient(restTemplate, springAppName); return new TestRibbonClient(restTemplate, springAppName);
} }
} }
} }

View File

@@ -1,37 +1,55 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import java.util.Arrays;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import org.springframework.cloud.commons.util.InetUtils; import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties; import org.springframework.cloud.commons.util.InetUtilsProperties;
import java.util.Arrays;
import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.then;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class ZookeeperDiscoveryPropertiesTest { public class ZookeeperDiscoveryPropertiesTest {
private String root; private String root;
public ZookeeperDiscoveryPropertiesTest(String root) { public ZookeeperDiscoveryPropertiesTest(String root) {
this.root = root; this.root = root;
} }
@Parameterized.Parameters(name = "With root {0}") @Parameterized.Parameters(name = "With root {0}")
public static Iterable<String> rootVariations() { public static Iterable<String> rootVariations() {
return Arrays.asList("es", "es/","/es"); return Arrays.asList("es", "es/", "/es");
} }
@Test @Test
public void should_escape_root() { public void should_escape_root() {
// given: // given:
ZookeeperDiscoveryProperties zookeeperDiscoveryProperties = new ZookeeperDiscoveryProperties(new InetUtils(new InetUtilsProperties())); ZookeeperDiscoveryProperties zookeeperDiscoveryProperties = new ZookeeperDiscoveryProperties(
// when: new InetUtils(new InetUtilsProperties()));
zookeeperDiscoveryProperties.setRoot(root); // when:
// then: zookeeperDiscoveryProperties.setRoot(root);
then(zookeeperDiscoveryProperties.getRoot()).isEqualTo("/es"); // then:
} then(zookeeperDiscoveryProperties.getRoot()).isEqualTo("/es");
}
} }

View File

@@ -1,7 +1,24 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -17,10 +34,10 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author wmz7year * @author wmz7year
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(properties = {"pring.application.name=testZookeeperDiscovery", @SpringBootTest(properties = { "pring.application.name=testZookeeperDiscovery",
"spring.cloud.zookeeper.discovery.instance-id=zkpropstestid-123", "spring.cloud.zookeeper.discovery.instance-id=zkpropstestid-123",
"spring.cloud.zookeeper.discovery.preferIpAddress=true", "spring.cloud.zookeeper.discovery.preferIpAddress=true",
"spring.cloud.zookeeper.discovery.instanceIpAddress=1.1.1.1"}, "spring.cloud.zookeeper.discovery.instanceIpAddress=1.1.1.1" },
classes = ZookeeperDiscoveryPropertiesTests.Config.class, classes = ZookeeperDiscoveryPropertiesTests.Config.class,
webEnvironment = WebEnvironment.RANDOM_PORT) webEnvironment = WebEnvironment.RANDOM_PORT)
public class ZookeeperDiscoveryPropertiesTests { public class ZookeeperDiscoveryPropertiesTests {
@@ -30,7 +47,8 @@ public class ZookeeperDiscoveryPropertiesTests {
@Test @Test
public void testPreferIpAddress() { public void testPreferIpAddress() {
assertThat(this.discoveryProperties.getInstanceId()).isEqualTo("zkpropstestid-123"); assertThat(this.discoveryProperties.getInstanceId())
.isEqualTo("zkpropstestid-123");
assertThat(this.discoveryProperties.getInstanceHost()).isEqualTo("1.1.1.1"); assertThat(this.discoveryProperties.getInstanceHost()).isEqualTo("1.1.1.1");
} }
@@ -40,4 +58,5 @@ public class ZookeeperDiscoveryPropertiesTests {
static class Config { static class Config {
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.cloud.zookeeper.discovery;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -42,13 +43,10 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoverySecurePortTests.Config.class, @SpringBootTest(classes = ZookeeperDiscoverySecurePortTests.Config.class, properties = {
properties = { "feign.hystrix.enabled=false",
"feign.hystrix.enabled=false", "spring.cloud.zookeeper.discovery.uriSpec={scheme}://{address}:{port}/contextPath",
"spring.cloud.zookeeper.discovery.uriSpec={scheme}://{address}:{port}/contextPath", "spring.cloud.zookeeper.discovery.instance-ssl-port=8443" }, webEnvironment = RANDOM_PORT)
"spring.cloud.zookeeper.discovery.instance-ssl-port=8443",
},
webEnvironment = RANDOM_PORT)
@ActiveProfiles("ribbon") @ActiveProfiles("ribbon")
@DirtiesContext @DirtiesContext
public class ZookeeperDiscoverySecurePortTests { public class ZookeeperDiscoverySecurePortTests {
@@ -67,10 +65,12 @@ public class ZookeeperDiscoverySecurePortTests {
@Test @Test
public void zookeeperServerIntrospectorWorks() { public void zookeeperServerIntrospectorWorks() {
ServerIntrospector serverIntrospector = this.clientFactory.getInstance(springAppName, ServerIntrospector.class); ServerIntrospector serverIntrospector = this.clientFactory
.getInstance(springAppName, ServerIntrospector.class);
then(serverIntrospector).isInstanceOf(ZookeeperServerIntrospector.class); then(serverIntrospector).isInstanceOf(ZookeeperServerIntrospector.class);
ZookeeperServer zookeeperServer = new ZookeeperServer(this.zookeeperRegistration.getServiceInstance()); ZookeeperServer zookeeperServer = new ZookeeperServer(
this.zookeeperRegistration.getServiceInstance());
then(serverIntrospector.isSecure(zookeeperServer)).isTrue(); then(serverIntrospector.isSecure(zookeeperServer)).isTrue();
} }
@@ -82,7 +82,8 @@ public class ZookeeperDiscoverySecurePortTests {
@Test @Test
public void shouldSetServiceInstanceSslPort() { public void shouldSetServiceInstanceSslPort() {
then(this.zookeeperRegistration.getServiceInstance().getSslPort()).isEqualTo(8443); then(this.zookeeperRegistration.getServiceInstance().getSslPort())
.isEqualTo(8443);
} }
@Configuration @Configuration
@@ -90,6 +91,7 @@ public class ZookeeperDiscoverySecurePortTests {
@Import(CommonTestConfig.class) @Import(CommonTestConfig.class)
@Profile("ribbon") @Profile("ribbon")
static class Config { static class Config {
} }
} }

View File

@@ -1,9 +1,28 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery;
import java.util.List; import java.util.List;
import com.jayway.awaitility.Awaitility;
import com.toomuchcoding.jsonassert.JsonPath;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -30,9 +49,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.jayway.awaitility.Awaitility;
import com.toomuchcoding.jsonassert.JsonPath;
import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
import static org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient.BASE_PATH; import static org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient.BASE_PATH;
@@ -42,57 +58,72 @@ import static org.springframework.cloud.zookeeper.discovery.test.TestRibbonClien
* @author Tim Ysewyn * @author Tim Ysewyn
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryTests.Config.class, @SpringBootTest(classes = ZookeeperDiscoveryTests.Config.class, properties = {
properties = { "feign.hystrix.enabled=false",
"feign.hystrix.enabled=false", "spring.cloud.zookeeper.discovery.uri-spec={scheme}://{address}:{port}/contextPath",
"spring.cloud.zookeeper.discovery.uri-spec={scheme}://{address}:{port}/contextPath", "management.endpoints.web.exposure.include=*" }, webEnvironment = RANDOM_PORT)
"management.endpoints.web.exposure.include=*"
},
webEnvironment = RANDOM_PORT)
@ActiveProfiles("ribbon") @ActiveProfiles("ribbon")
@DirtiesContext @DirtiesContext
public class ZookeeperDiscoveryTests { public class ZookeeperDiscoveryTests {
@Autowired TestRibbonClient testRibbonClient; @Autowired
@Autowired DiscoveryClient discoveryClient; TestRibbonClient testRibbonClient;
@Autowired ServiceInstanceRegistration serviceDiscovery;
@Value("${spring.application.name}") String springAppName;
@Autowired IdUsingFeignClient idUsingFeignClient;
@Autowired Registration registration;
@Test public void should_find_the_app_by_its_name_via_Ribbon() { @Autowired
//expect: DiscoveryClient discoveryClient;
@Autowired
ServiceInstanceRegistration serviceDiscovery;
@Value("${spring.application.name}")
String springAppName;
@Autowired
IdUsingFeignClient idUsingFeignClient;
@Autowired
Registration registration;
@Test
public void should_find_the_app_by_its_name_via_Ribbon() {
// expect:
then(registeredServiceStatusViaServiceName()).isEqualTo("UP"); then(registeredServiceStatusViaServiceName()).isEqualTo("UP");
} }
@Test public void should_find_a_collaborator_via_discovery_client() { @Test
//given: public void should_find_a_collaborator_via_discovery_client() {
List<ServiceInstance> instances = this.discoveryClient.getInstances(this.springAppName); // given:
List<ServiceInstance> instances = this.discoveryClient
.getInstances(this.springAppName);
ServiceInstance instance = instances.get(0); ServiceInstance instance = instances.get(0);
//expect: // expect:
then(registeredServiceStatus(instance)).isEqualTo("UP"); then(registeredServiceStatus(instance)).isEqualTo("UP");
then(instance.getInstanceId()).isEqualTo("ribbon-instance-id-123"); then(instance.getInstanceId()).isEqualTo("ribbon-instance-id-123");
then(instance.getMetadata().get("testMetadataKey")).isEqualTo("testMetadataValue"); then(instance.getMetadata().get("testMetadataKey"))
.isEqualTo("testMetadataValue");
then(instance).isInstanceOf(ZookeeperServiceInstance.class); then(instance).isInstanceOf(ZookeeperServiceInstance.class);
ZookeeperServiceInstance zkInstance = (ZookeeperServiceInstance) instance; ZookeeperServiceInstance zkInstance = (ZookeeperServiceInstance) instance;
then(zkInstance.getServiceInstance().getId()).isEqualTo("ribbon-instance-id-123"); then(zkInstance.getServiceInstance().getId()).isEqualTo("ribbon-instance-id-123");
} }
@Test public void should_present_application_name_as_id_of_the_service_instance() { @Test
//given: public void should_present_application_name_as_id_of_the_service_instance() {
//expect: // given:
// expect:
then(this.springAppName).isEqualTo(this.registration.getServiceId()); then(this.springAppName).isEqualTo(this.registration.getServiceId());
} }
@Test public void should_service_instance_uri_match_uriSpec() { @Test
//given: public void should_service_instance_uri_match_uriSpec() {
//expect: // given:
// expect:
then(this.registration.getUri()).hasPath("/contextPath"); then(this.registration.getUri()).hasPath("/contextPath");
} }
@Test public void should_find_an_instance_using_feign_via_service_id() { @Test
public void should_find_an_instance_using_feign_via_service_id() {
final IdUsingFeignClient idUsingFeignClient = this.idUsingFeignClient; final IdUsingFeignClient idUsingFeignClient = this.idUsingFeignClient;
//expect: // expect:
Awaitility.await().until(() -> { Awaitility.await().until(() -> {
then(idUsingFeignClient.hi()).isNotEmpty(); then(idUsingFeignClient.hi()).isNotEmpty();
return true; return true;
@@ -100,23 +131,29 @@ public class ZookeeperDiscoveryTests {
} }
private String registeredServiceStatusViaServiceName() { private String registeredServiceStatusViaServiceName() {
return JsonPath.builder(this.testRibbonClient.thisHealthCheck()).field("status").read(String.class); return JsonPath.builder(this.testRibbonClient.thisHealthCheck()).field("status")
.read(String.class);
} }
private String registeredServiceStatus(ServiceInstance instance) { private String registeredServiceStatus(ServiceInstance instance) {
return JsonPath.builder(this.testRibbonClient.callOnUrl(instance.getHost()+":"+instance.getPort(), BASE_PATH + "/health")).field("status").read(String.class); return JsonPath.builder(this.testRibbonClient.callOnUrl(
instance.getHost() + ":" + instance.getPort(), BASE_PATH + "/health"))
.field("status").read(String.class);
} }
@Test public void should_properly_find_local_instance() { @Test
//expect: public void should_properly_find_local_instance() {
then(this.serviceDiscovery.getServiceInstance().getAddress()).isEqualTo(this.registration.getHost()); // expect:
then(this.serviceDiscovery.getServiceInstance().getAddress())
.isEqualTo(this.registration.getHost());
} }
@FeignClient("ribbonApp") @FeignClient("ribbonApp")
public interface IdUsingFeignClient { public interface IdUsingFeignClient {
@RequestMapping(method = RequestMethod.GET, value = "/hi") @RequestMapping(method = RequestMethod.GET, value = "/hi")
String hi(); String hi();
} }
@Configuration @Configuration
@@ -127,7 +164,8 @@ public class ZookeeperDiscoveryTests {
@RestController @RestController
static class Config { static class Config {
@Bean TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate, @Bean
TestRibbonClient testRibbonClient(@LoadBalanced RestTemplate restTemplate,
@Value("${spring.application.name}") String springAppName) { @Value("${spring.application.name}") String springAppName) {
return new TestRibbonClient(restTemplate, springAppName); return new TestRibbonClient(restTemplate, springAppName);
} }
@@ -136,14 +174,18 @@ public class ZookeeperDiscoveryTests {
public String hi() { public String hi() {
return "hi"; return "hi";
} }
} }
@Controller @Controller
@Profile("ribbon") @Profile("ribbon")
class PingController { class PingController {
@RequestMapping("/ping") String ping() { @RequestMapping("/ping")
String ping() {
return "pong"; return "pong";
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.util.List;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -29,31 +30,34 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertTrue; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperLifecycleRegistrationDisabledTests.TestPropsConfig.class, @SpringBootTest(classes = ZookeeperLifecycleRegistrationDisabledTests.TestPropsConfig.class, properties = {
properties = { "spring.application.name=myTestNotRegisteredService", "spring.application.name=myTestNotRegisteredService",
"spring.cloud.zookeeper.discovery.register=false", "spring.cloud.zookeeper.dependency.enabled=false"}, "spring.cloud.zookeeper.discovery.register=false",
webEnvironment = RANDOM_PORT) "spring.cloud.zookeeper.dependency.enabled=false" }, webEnvironment = RANDOM_PORT)
public class ZookeeperLifecycleRegistrationDisabledTests { public class ZookeeperLifecycleRegistrationDisabledTests {
@Autowired @Autowired
private ZookeeperDiscoveryClient client; private ZookeeperDiscoveryClient client;
@Test @Test
public void contextLoads() { public void contextLoads() {
List<ServiceInstance> instances = this.client.getInstances("myTestNotRegisteredService"); List<ServiceInstance> instances = this.client
assertTrue("service was registered", instances.isEmpty()); .getInstances("myTestNotRegisteredService");
assertThat(instances.isEmpty()).as("service was registered").isTrue();
} }
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@Import({ CommonTestConfig.class }) @Import({ CommonTestConfig.class })
static class TestPropsConfig { } static class TestPropsConfig {
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2017 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
package org.springframework.cloud.zookeeper.discovery; package org.springframework.cloud.zookeeper.discovery;
import com.jayway.awaitility.Awaitility;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
@@ -36,23 +38,24 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.then;
/** /**
* Test for gh-91, using s-c-zookeeper in a non-web app. * Test for gh-91, using s-c-zookeeper in a non-web app.
*
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
public class ZookeeprDiscoveryNonWebAppTests { public class ZookeeprDiscoveryNonWebAppTests {
TestingServer server; TestingServer server;
String connectionString; String connectionString;
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
this.server = new TestingServer(SocketUtils.findAvailableTcpPort()); this.server = new TestingServer(SocketUtils.findAvailableTcpPort());
this.connectionString = "--spring.cloud.zookeeper.connectString=" + this.server.getConnectString(); this.connectionString = "--spring.cloud.zookeeper.connectString="
+ this.server.getConnectString();
} }
@After @After
@@ -64,25 +67,29 @@ public class ZookeeprDiscoveryNonWebAppTests {
public void should_work_when_using_web_client_without_the_web_environment() public void should_work_when_using_web_client_without_the_web_environment()
throws Exception { throws Exception {
SpringApplication producerApp = new SpringApplicationBuilder(HelloProducer.class) SpringApplication producerApp = new SpringApplicationBuilder(HelloProducer.class)
.web(WebApplicationType.SERVLET) .web(WebApplicationType.SERVLET).build();
.build(); SpringApplication clientApplication = new SpringApplicationBuilder(
SpringApplication clientApplication = new SpringApplicationBuilder(HelloClient.class) HelloClient.class).web(WebApplicationType.NONE).build();
.web(WebApplicationType.NONE)
.build();
try (ConfigurableApplicationContext producerContext = producerApp.run(this.connectionString, "--server.port=0", try (ConfigurableApplicationContext producerContext = producerApp.run(
this.connectionString, "--server.port=0",
"--spring.application.name=hello-world", "--debug")) { "--spring.application.name=hello-world", "--debug")) {
try (final ConfigurableApplicationContext context = clientApplication.run(this.connectionString, try (ConfigurableApplicationContext context = clientApplication.run(
this.connectionString,
"--spring.cloud.zookeeper.discovery.register=false")) { "--spring.cloud.zookeeper.discovery.register=false")) {
Awaitility.await().until(new Runnable() { Awaitility.await().until(new Runnable() {
@Override public void run() { @Override
public void run() {
try { try {
HelloClient bean = context.getBean(HelloClient.class); HelloClient bean = context.getBean(HelloClient.class);
then(bean.discoveryClient.getServices()).isNotEmpty(); then(bean.discoveryClient.getServices()).isNotEmpty();
then(bean.discoveryClient.getInstances("hello-world")).isNotEmpty(); then(bean.discoveryClient.getInstances("hello-world"))
String string = bean.restTemplate.getForObject("http://hello-world/", String.class); .isNotEmpty();
String string = bean.restTemplate
.getForObject("http://hello-world/", String.class);
then(string).isEqualTo("foo"); then(string).isEqualTo("foo");
} catch (IllegalStateException e) { }
catch (IllegalStateException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
@@ -91,9 +98,10 @@ public class ZookeeprDiscoveryNonWebAppTests {
} }
} }
@EnableAutoConfiguration(exclude = {JmxAutoConfiguration.class}) @EnableAutoConfiguration(exclude = { JmxAutoConfiguration.class })
@Configuration @Configuration
static class HelloClient { static class HelloClient {
@LoadBalanced @LoadBalanced
@Bean @Bean
RestTemplate restTemplate() { RestTemplate restTemplate() {
@@ -103,10 +111,12 @@ public class ZookeeprDiscoveryNonWebAppTests {
@Autowired @Autowired
DiscoveryClient discoveryClient; DiscoveryClient discoveryClient;
@Autowired RestTemplate restTemplate; @Autowired
RestTemplate restTemplate;
} }
@EnableAutoConfiguration(exclude = {JmxAutoConfiguration.class}) @EnableAutoConfiguration(exclude = { JmxAutoConfiguration.class })
@RestController @RestController
static class HelloProducer { static class HelloProducer {
@@ -116,4 +126,5 @@ public class ZookeeprDiscoveryNonWebAppTests {
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.assertEquals; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -70,14 +70,14 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests {
"spring.cloud.zookeeper.discovery.instance-port:7001", "spring.cloud.zookeeper.discovery.instance-port:7001",
"spring.cloud.zookeeper.discovery.instance-host:foo", "spring.cloud.zookeeper.discovery.instance-host:foo",
"spring.cloud.config.discovery.service-id:configserver"); "spring.cloud.config.discovery.service-id:configserver");
assertEquals( 1, this.context assertThat(this.context.getBeanNamesForType(
.getBeanNamesForType(ZookeeperConfigServerAutoConfiguration.class).length); ZookeeperConfigServerAutoConfiguration.class).length).isEqualTo(1);
ZookeeperDiscoveryClient client = this.context.getParent().getBean( ZookeeperDiscoveryClient client = this.context.getParent()
ZookeeperDiscoveryClient.class); .getBean(ZookeeperDiscoveryClient.class);
verify(client, atLeast(2)).getInstances("configserver"); verify(client, atLeast(2)).getInstances("configserver");
ConfigClientProperties locator = this.context ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class); .getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getUri()[0]); assertThat(locator.getUri()[0]).isEqualTo("http://foo:7001/");
} }
private void setup(String... env) { private void setup(String... env) {
@@ -92,7 +92,8 @@ public class DiscoveryClientConfigServiceAutoConfigurationTests {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
this.context.setParent(parent); this.context.setParent(parent);
this.context.register(PropertyPlaceholderAutoConfiguration.class, this.context.register(PropertyPlaceholderAutoConfiguration.class,
ZookeeperConfigServerAutoConfiguration.class, ZookeeperAutoConfiguration.class, ZookeeperConfigServerAutoConfiguration.class,
ZookeeperAutoConfiguration.class,
ZookeeperDiscoveryClientConfiguration.class); ZookeeperDiscoveryClientConfiguration.class);
this.context.refresh(); this.context.refresh();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2016 the original author or authors. * Copyright 2015-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
/** /**
* @author Dave Syer * @author Dave Syer
@@ -48,16 +47,19 @@ public class ZookeeperConfigServerAutoConfigurationTests {
public void offByDefault() { public void offByDefault() {
this.context = new AnnotationConfigApplicationContext( this.context = new AnnotationConfigApplicationContext(
ZookeeperConfigServerAutoConfiguration.class); ZookeeperConfigServerAutoConfiguration.class);
assertEquals(0, assertThat(this.context
this.context.getBeanNamesForType(ZookeeperDiscoveryProperties.class).length); .getBeanNamesForType(ZookeeperDiscoveryProperties.class).length)
.isEqualTo(0);
} }
@Test @Test
public void onWhenRequested() { public void onWhenRequested() {
setup("spring.cloud.config.server.prefix=/config"); setup("spring.cloud.config.server.prefix=/config");
assertEquals(1, assertThat(this.context
this.context.getBeanNamesForType(ZookeeperDiscoveryProperties.class).length); .getBeanNamesForType(ZookeeperDiscoveryProperties.class).length)
ZookeeperDiscoveryProperties properties = this.context.getBean(ZookeeperDiscoveryProperties.class); .isEqualTo(1);
ZookeeperDiscoveryProperties properties = this.context
.getBean(ZookeeperDiscoveryProperties.class);
assertThat(properties.getMetadata()).containsEntry("configPath", "/config"); assertThat(properties.getMetadata()).containsEntry("configPath", "/config");
} }
@@ -66,8 +68,7 @@ public class ZookeeperConfigServerAutoConfigurationTests {
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
ZookeeperConfigServerAutoConfiguration.class, ZookeeperConfigServerAutoConfiguration.class,
ConfigServerProperties.class, ZookeeperDiscoveryProperties.class) ConfigServerProperties.class, ZookeeperDiscoveryProperties.class)
.web(WebApplicationType.NONE) .web(WebApplicationType.NONE).properties(env).run();
.properties(env).run();
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.Collection; import java.util.Collection;
@@ -24,7 +40,8 @@ import static org.assertj.core.api.BDDAssertions.then;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(CommonTestConfig.class) @Import(CommonTestConfig.class)
@EnableFeignClients(basePackageClasses = {AliasUsingFeignClient.class, IdUsingFeignClient.class}) @EnableFeignClients(basePackageClasses = { AliasUsingFeignClient.class,
IdUsingFeignClient.class })
public class DependencyConfig { public class DependencyConfig {
@Bean @Bean
@@ -61,17 +78,21 @@ class PortListener implements ApplicationListener<WebServerInitializedEvent> {
@FeignClient("someAlias") @FeignClient("someAlias")
interface AliasUsingFeignClient { interface AliasUsingFeignClient {
@RequestMapping(method = RequestMethod.GET, value = "/application/beans") @RequestMapping(method = RequestMethod.GET, value = "/application/beans")
String getBeans(); String getBeans();
@RequestMapping(method = RequestMethod.GET, value = "/checkHeaders") @RequestMapping(method = RequestMethod.GET, value = "/checkHeaders")
String checkHeaders(); String checkHeaders();
} }
@FeignClient("nameWithoutAlias") @FeignClient("nameWithoutAlias")
interface IdUsingFeignClient { interface IdUsingFeignClient {
@RequestMapping(method = RequestMethod.GET, value = "/application/beans") @RequestMapping(method = RequestMethod.GET, value = "/application/beans")
String getBeans(); String getBeans();
} }
@RestController @RestController
@@ -83,21 +104,24 @@ class PingController {
this.portListener = portListener; this.portListener = portListener;
} }
@RequestMapping("/ping") String ping() { @RequestMapping("/ping")
String ping() {
return "pong"; return "pong";
} }
@RequestMapping("/port") Integer port() { @RequestMapping("/port")
Integer port() {
return this.portListener.getPort(); return this.portListener.getPort();
} }
@RequestMapping("/checkHeaders") String checkHeaders(@RequestHeader("Content-Type") String contentType, @RequestMapping("/checkHeaders")
@RequestHeader("header1") String checkHeaders(@RequestHeader("Content-Type") String contentType,
Collection<String> header1, @RequestHeader("header1") Collection<String> header1,
@RequestHeader("header2") Collection<String> header2) { @RequestHeader("header2") Collection<String> header2) {
then(contentType).isEqualTo("application/vnd.newsletter.v1+json"); then(contentType).isEqualTo("application/vnd.newsletter.v1+json");
then(header1).containsExactly("value1"); then(header1).containsExactly("value1");
then(header2).containsExactly("value2"); then(header2).containsExactly("value2");
return "ok"; return "ok";
} }
} }

View File

@@ -1,13 +1,33 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import com.jayway.awaitility.Awaitility;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.NoOpPing;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -25,35 +45,36 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.SocketUtils; import org.springframework.util.SocketUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import com.jayway.awaitility.Awaitility;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.NoOpPing;
/** /**
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = StickyRuleTests.Config.class, @SpringBootTest(classes = StickyRuleTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("loadbalancerclient") @ActiveProfiles("loadbalancerclient")
public class StickyRuleTests { public class StickyRuleTests {
@Autowired LoadBalancerClient loadBalancerClient; @Autowired
@Autowired DiscoveryClient discoveryClient; LoadBalancerClient loadBalancerClient;
@Autowired
DiscoveryClient discoveryClient;
@Test @Test
public void should_use_sticky_load_balancing_strategy_taken_from_Zookeeper_dependencies() { public void should_use_sticky_load_balancing_strategy_taken_from_Zookeeper_dependencies() {
//given: // given:
System.setProperty("spring.cloud.zookeeper.dependency.ribbon.loadbalancer.checkping", "false"); System.setProperty(
//expect: "spring.cloud.zookeeper.dependency.ribbon.loadbalancer.checkping",
thereAreTwoRegisteredServices(); "false");
URI uri = getUriForAlias(); // expect:
Awaitility.await().until(uriMatchesTwice(uri)); thereAreTwoRegisteredServices();
URI uri = getUriForAlias();
Awaitility.await().until(uriMatchesTwice(uri));
} }
private Callable<Boolean> uriMatchesTwice(final URI uri) { private Callable<Boolean> uriMatchesTwice(final URI uri) {
return new Callable<Boolean>() { return new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
return uriMatches() && uriMatches(); return uriMatches() && uriMatches();
} }
@@ -73,38 +94,47 @@ public class StickyRuleTests {
return alias != null ? alias.getUri() : null; return alias != null ? alias.getUri() : null;
} }
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@Profile("loadbalancerclient") @Profile("loadbalancerclient")
static class Config { static class Config {
@Bean @Bean
@LoadBalanced RestTemplate loadBalancedRestTemplate() { @LoadBalanced
RestTemplate loadBalancedRestTemplate() {
return new RestTemplate(); return new RestTemplate();
} }
@Bean(destroyMethod = "close") TestingServer testingServer() throws Exception { @Bean(destroyMethod = "close")
TestingServer testingServer() throws Exception {
return new TestingServer(SocketUtils.findAvailableTcpPort()); return new TestingServer(SocketUtils.findAvailableTcpPort());
} }
@Bean ZookeeperProperties zookeeperProperties() throws Exception { @Bean
ZookeeperProperties zookeeperProperties() throws Exception {
ZookeeperProperties zookeeperProperties = new ZookeeperProperties(); ZookeeperProperties zookeeperProperties = new ZookeeperProperties();
zookeeperProperties.setConnectString("localhost:"+ testingServer().getPort()); zookeeperProperties
.setConnectString("localhost:" + testingServer().getPort());
return zookeeperProperties; return zookeeperProperties;
} }
@Bean(initMethod = "start", destroyMethod = "stop") @Bean(initMethod = "start", destroyMethod = "stop")
TestServiceRegistrar serviceOne(CuratorFramework curatorFramework) { TestServiceRegistrar serviceOne(CuratorFramework curatorFramework) {
return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(), curatorFramework); return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(),
curatorFramework);
} }
@Bean(initMethod = "start", destroyMethod = "stop") TestServiceRegistrar serviceTwo(CuratorFramework curatorFramework) { @Bean(initMethod = "start", destroyMethod = "stop")
return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(), curatorFramework); TestServiceRegistrar serviceTwo(CuratorFramework curatorFramework) {
return new TestServiceRegistrar(SocketUtils.findAvailableTcpPort(),
curatorFramework);
} }
@Bean IPing noOpPing() { @Bean
IPing noOpPing() {
return new NoOpPing(); return new NoOpPing();
} }
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import org.junit.Test; import org.junit.Test;
@@ -11,30 +27,31 @@ public class StubsConfigurationTests {
@Test @Test
public void should_return_empty_colon_separated_dependency_notation_if_empty_path_has_been_provided() { public void should_return_empty_colon_separated_dependency_notation_if_empty_path_has_been_provided() {
//given: // given:
String path = ""; String path = "";
//when: // when:
StubsConfiguration stubsConfiguration = new StubsConfiguration(path); StubsConfiguration stubsConfiguration = new StubsConfiguration(path);
//then: // then:
then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo(""); then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo("");
} }
@Test @Test
public void should_return_empty_colon_separated_dependency_notation_if_invalid_path_has_been_provided() { public void should_return_empty_colon_separated_dependency_notation_if_invalid_path_has_been_provided() {
//given: // given:
String path = "pl/"; String path = "pl/";
//when: // when:
StubsConfiguration stubsConfiguration = new StubsConfiguration(path); StubsConfiguration stubsConfiguration = new StubsConfiguration(path);
//then: // then:
then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo(""); then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo("");
} }
@Test @Test
public void should_properly_parse_invalid_colon_separated_path_into_empty_notation() { public void should_properly_parse_invalid_colon_separated_path_into_empty_notation() {
//given: // given:
String path = "pl/a"; String path = "pl/a";
//when: // when:
StubsConfiguration stubsConfiguration = new StubsConfiguration(path); StubsConfiguration stubsConfiguration = new StubsConfiguration(path);
//then: // then:
then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo(""); then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo("");
then(stubsConfiguration.getStubsGroupId()).isEqualTo(""); then(stubsConfiguration.getStubsGroupId()).isEqualTo("");
then(stubsConfiguration.getStubsArtifactId()).isEqualTo(""); then(stubsConfiguration.getStubsArtifactId()).isEqualTo("");
@@ -43,12 +60,14 @@ public class StubsConfigurationTests {
@Test @Test
public void should_parse_the_path_into_group_artifact_and_classifier() { public void should_parse_the_path_into_group_artifact_and_classifier() {
//given: // given:
String path = "pl/a"; String path = "pl/a";
//when: // when:
StubsConfiguration stubsConfiguration = new StubsConfiguration(new StubsConfiguration.DependencyPath(path)); StubsConfiguration stubsConfiguration = new StubsConfiguration(
//then: new StubsConfiguration.DependencyPath(path));
then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo("pl:a:stubs"); // then:
then(stubsConfiguration.toColonSeparatedDependencyNotation())
.isEqualTo("pl:a:stubs");
then(stubsConfiguration.getStubsGroupId()).isEqualTo("pl"); then(stubsConfiguration.getStubsGroupId()).isEqualTo("pl");
then(stubsConfiguration.getStubsArtifactId()).isEqualTo("a"); then(stubsConfiguration.getStubsArtifactId()).isEqualTo("a");
then(stubsConfiguration.getStubsClassifier()).isEqualTo("stubs"); then(stubsConfiguration.getStubsClassifier()).isEqualTo("stubs");
@@ -56,13 +75,15 @@ public class StubsConfigurationTests {
@Test @Test
public void should_properly_set_group_artifact_and_classifier() { public void should_properly_set_group_artifact_and_classifier() {
//when: // when:
StubsConfiguration stubsConfiguration = new StubsConfiguration("pl", "a", "superstubs"); StubsConfiguration stubsConfiguration = new StubsConfiguration("pl", "a",
//then: "superstubs");
then(stubsConfiguration.toColonSeparatedDependencyNotation()).isEqualTo("pl:a:superstubs"); // then:
then(stubsConfiguration.toColonSeparatedDependencyNotation())
.isEqualTo("pl:a:superstubs");
then(stubsConfiguration.getStubsGroupId()).isEqualTo("pl"); then(stubsConfiguration.getStubsGroupId()).isEqualTo("pl");
then(stubsConfiguration.getStubsArtifactId()).isEqualTo("a"); then(stubsConfiguration.getStubsArtifactId()).isEqualTo("a");
then(stubsConfiguration.getStubsClassifier()).isEqualTo("superstubs"); then(stubsConfiguration.getStubsClassifier()).isEqualTo("superstubs");
} }
} }

View File

@@ -1,51 +1,71 @@
package org.springframework.cloud.zookeeper.discovery.dependency; /*
* Copyright 2015-2019 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.
*/
import org.junit.Test; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.junit.Test;
import static org.assertj.core.api.BDDAssertions.then; import static org.assertj.core.api.BDDAssertions.then;
public class ZookeeperDependenciesTest { public class ZookeeperDependenciesTest {
@Test @Test
public void should_properly_sanitize_dependency_path() { public void should_properly_sanitize_dependency_path() {
// given: // given:
Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>(); Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>();
ZookeeperDependency cat = new ZookeeperDependency(); ZookeeperDependency cat = new ZookeeperDependency();
cat.setPath("/cats/cat"); cat.setPath("/cats/cat");
dependencies.put("cat", cat); dependencies.put("cat", cat);
ZookeeperDependency dog = new ZookeeperDependency(); ZookeeperDependency dog = new ZookeeperDependency();
dog.setPath("dogs/dog"); dog.setPath("dogs/dog");
dependencies.put("dog", dog); dependencies.put("dog", dog);
ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies(); ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies();
zookeeperDependencies.setDependencies(dependencies); zookeeperDependencies.setDependencies(dependencies);
// when: // when:
zookeeperDependencies.init(); zookeeperDependencies.init();
// then: // then:
then(zookeeperDependencies.getDependencies().get("cat").getPath()).isEqualTo("/cats/cat"); then(zookeeperDependencies.getDependencies().get("cat").getPath())
then(zookeeperDependencies.getDependencies().get("dog").getPath()).isEqualTo("/dogs/dog"); .isEqualTo("/cats/cat");
} then(zookeeperDependencies.getDependencies().get("dog").getPath())
.isEqualTo("/dogs/dog");
}
@Test @Test
public void should_properly_sanitize_dependency_path_with_prefix() { public void should_properly_sanitize_dependency_path_with_prefix() {
// given: // given:
Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>(); Map<String, ZookeeperDependency> dependencies = new LinkedHashMap<>();
ZookeeperDependency cat = new ZookeeperDependency(); ZookeeperDependency cat = new ZookeeperDependency();
cat.setPath("/cats/cat"); cat.setPath("/cats/cat");
dependencies.put("cat", cat); dependencies.put("cat", cat);
ZookeeperDependency dog = new ZookeeperDependency(); ZookeeperDependency dog = new ZookeeperDependency();
dog.setPath("dogs/dog"); dog.setPath("dogs/dog");
dependencies.put("dog", dog); dependencies.put("dog", dog);
ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies(); ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies();
zookeeperDependencies.setPrefix("animals/"); zookeeperDependencies.setPrefix("animals/");
zookeeperDependencies.setDependencies(dependencies); zookeeperDependencies.setDependencies(dependencies);
// when: // when:
zookeeperDependencies.init(); zookeeperDependencies.init();
// then: // then:
then(zookeeperDependencies.getDependencies().get("cat").getPath()).isEqualTo("/animals/cats/cat"); then(zookeeperDependencies.getDependencies().get("cat").getPath())
then(zookeeperDependencies.getDependencies().get("dog").getPath()).isEqualTo("/animals/dogs/dog"); .isEqualTo("/animals/cats/cat");
} then(zookeeperDependencies.getDependencies().get("dog").getPath())
.isEqualTo("/animals/dogs/dog");
}
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.Collection; import java.util.Collection;
@@ -16,18 +32,14 @@ import static org.assertj.core.api.BDDAssertions.then;
public class ZookeeperDependenciesTests { public class ZookeeperDependenciesTests {
private static final ZookeeperDependency EXPECTED_DEPENDENCY = new ZookeeperDependency( private static final ZookeeperDependency EXPECTED_DEPENDENCY = new ZookeeperDependency(
"path", "path", LoadBalancerType.RANDOM, "contentTypeTemplate", "version",
LoadBalancerType.RANDOM, defaultHeader(), false, "");
"contentTypeTemplate",
"version",
defaultHeader(),
false,
""
);
private static final Map<String, ZookeeperDependency> DEPENDENCIES = defaultDependencies(); private static final Map<String, ZookeeperDependency> DEPENDENCIES = defaultDependencies();
private static Map<String, Collection<String>> defaultHeader() { private static Map<String, Collection<String>> defaultHeader() {
return Collections.singletonMap("header", (Collection<String>) Collections.singletonList("value")); return Collections.singletonMap("header",
(Collection<String>) Collections.singletonList("value"));
} }
private static Map<String, ZookeeperDependency> defaultDependencies() { private static Map<String, ZookeeperDependency> defaultDependencies() {
@@ -37,59 +49,72 @@ public class ZookeeperDependenciesTests {
} }
ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies(); ZookeeperDependencies zookeeperDependencies = new ZookeeperDependencies();
@Before @Before
public void setup() { public void setup() {
this.zookeeperDependencies.setDependencies(DEPENDENCIES); this.zookeeperDependencies.setDependencies(DEPENDENCIES);
} }
@Test public void should_retrieve_dependency_dependency_for_good_path() { @Test
public void should_retrieve_dependency_dependency_for_good_path() {
// expect: // expect:
then(this.zookeeperDependencies.getDependencyForPath("path")).isEqualTo(EXPECTED_DEPENDENCY); then(this.zookeeperDependencies.getDependencyForPath("path"))
.isEqualTo(EXPECTED_DEPENDENCY);
} }
@Test public void should_retrieve_null_dependency_dependency_for_bad_path() { @Test
public void should_retrieve_null_dependency_dependency_for_bad_path() {
// expect: // expect:
then(this.zookeeperDependencies.getDependencyForPath("unknownPath")).isNull(); then(this.zookeeperDependencies.getDependencyForPath("unknownPath")).isNull();
} }
@Test public void should_retrieve_dependency_for_good_alias() { @Test
public void should_retrieve_dependency_for_good_alias() {
// expect: // expect:
then(this.zookeeperDependencies.getDependencyForAlias("alias")).isEqualTo(EXPECTED_DEPENDENCY); then(this.zookeeperDependencies.getDependencyForAlias("alias"))
.isEqualTo(EXPECTED_DEPENDENCY);
} }
@Test public void should_retrieve_null_dependency_for_bad_alias() { @Test
public void should_retrieve_null_dependency_for_bad_alias() {
// expect: // expect:
then(this.zookeeperDependencies.getDependencyForAlias("unknownAlias")).isNull(); then(this.zookeeperDependencies.getDependencyForAlias("unknownAlias")).isNull();
} }
@Test public void should_retrieve_alias_for_good_path() { @Test
public void should_retrieve_alias_for_good_path() {
// expect: // expect:
then(this.zookeeperDependencies.getAliasForPath("path")).isEqualTo("alias"); then(this.zookeeperDependencies.getAliasForPath("path")).isEqualTo("alias");
} }
@Test public void should_retrieve_empty_alias_for_bad_path() { @Test
public void should_retrieve_empty_alias_for_bad_path() {
// expect: // expect:
then(this.zookeeperDependencies.getAliasForPath("unkownPath")).isEmpty(); then(this.zookeeperDependencies.getAliasForPath("unkownPath")).isEmpty();
} }
@Test public void should_retrieve_path_for_good_alias() { @Test
public void should_retrieve_path_for_good_alias() {
// expect: // expect:
then(this.zookeeperDependencies.getPathForAlias("alias")).isEqualTo("path"); then(this.zookeeperDependencies.getPathForAlias("alias")).isEqualTo("path");
} }
@Test public void should_retrieve_empty_path_for_bad_alias() { @Test
public void should_retrieve_empty_path_for_bad_alias() {
// expect: // expect:
then(this.zookeeperDependencies.getPathForAlias("unknownAlias")).isEmpty(); then(this.zookeeperDependencies.getPathForAlias("unknownAlias")).isEmpty();
} }
@Test public void should_successfully_replace_version_in_content_type_template() { @Test
public void should_successfully_replace_version_in_content_type_template() {
// given: // given:
ZookeeperDependency zookeeperDependency = new ZookeeperDependency(); ZookeeperDependency zookeeperDependency = new ZookeeperDependency();
zookeeperDependency.setContentTypeTemplate("application/vnd.some-service.$version+json"); zookeeperDependency
.setContentTypeTemplate("application/vnd.some-service.$version+json");
zookeeperDependency.setVersion("v1"); zookeeperDependency.setVersion("v1");
// expect: // expect:
then(zookeeperDependency.getContentTypeWithVersion()).isEqualTo("application/vnd.some-service.v1+json"); then(zookeeperDependency.getContentTypeWithVersion())
.isEqualTo("application/vnd.some-service.v1+json");
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.util.List; import java.util.List;
@@ -6,6 +22,7 @@ import java.util.concurrent.Callable;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -26,135 +43,168 @@ import static org.springframework.cloud.zookeeper.discovery.test.TestRibbonClien
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = ZookeeperDiscoveryWithDependenciesIntegrationTests.Config.class, @SpringBootTest(classes = ZookeeperDiscoveryWithDependenciesIntegrationTests.Config.class, properties = {
properties = {"feign.hystrix.enabled=false", "debug=true", "management.endpoints.web.exposure.include=*"}, "feign.hystrix.enabled=false", "debug=true",
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) "management.endpoints.web.exposure.include=*" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("dependencies") @ActiveProfiles("dependencies")
public class ZookeeperDiscoveryWithDependenciesIntegrationTests { public class ZookeeperDiscoveryWithDependenciesIntegrationTests {
@Autowired TestRibbonClient testRibbonClient; @Autowired
@Autowired DiscoveryClient discoveryClient; TestRibbonClient testRibbonClient;
@Autowired AliasUsingFeignClient aliasUsingFeignClient;
@Autowired IdUsingFeignClient idUsingFeignClient;
@Autowired ZookeeperDependencies zookeeperDependencies;
@Test public void should_find_an_instance_via_path_when_alias_is_not_found() { @Autowired
DiscoveryClient discoveryClient;
@Autowired
AliasUsingFeignClient aliasUsingFeignClient;
@Autowired
IdUsingFeignClient idUsingFeignClient;
@Autowired
ZookeeperDependencies zookeeperDependencies;
@Test
public void should_find_an_instance_via_path_when_alias_is_not_found() {
// given: // given:
final DiscoveryClient discoveryClient = this.discoveryClient; final DiscoveryClient discoveryClient = this.discoveryClient;
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
return !discoveryClient.getInstances("nameWithoutAlias").isEmpty(); return !discoveryClient.getInstances("nameWithoutAlias").isEmpty();
} }
}); });
} }
@Test public void should_fill_out_properly_the_stub_section_of_a_dependency() { @Test
public void should_fill_out_properly_the_stub_section_of_a_dependency() {
// given: // given:
StubsConfiguration stubsConfiguration = this.zookeeperDependencies.getDependencies().get("someAlias").getStubsConfiguration(); StubsConfiguration stubsConfiguration = this.zookeeperDependencies
.getDependencies().get("someAlias").getStubsConfiguration();
// expect: // expect:
then(stubsConfiguration.getStubsGroupId()).isEqualTo("org.springframework"); then(stubsConfiguration.getStubsGroupId()).isEqualTo("org.springframework");
then(stubsConfiguration.getStubsArtifactId()).isEqualTo("foo"); then(stubsConfiguration.getStubsArtifactId()).isEqualTo("foo");
then(stubsConfiguration.getStubsClassifier()).isEqualTo("stubs"); then(stubsConfiguration.getStubsClassifier()).isEqualTo("stubs");
} }
@Ignore //FIXME 2.0.0 @Ignore // FIXME 2.0.0
@Test public void should_find_an_instance_using_feign_via_serviceID_when_alias_is_not_found() { @Test
public void should_find_an_instance_using_feign_via_serviceID_when_alias_is_not_found() {
// given: // given:
final IdUsingFeignClient idUsingFeignClient = this.idUsingFeignClient; final IdUsingFeignClient idUsingFeignClient = this.idUsingFeignClient;
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
then(idUsingFeignClient.getBeans()).isNotEmpty(); then(idUsingFeignClient.getBeans()).isNotEmpty();
return true; return true;
} }
}); });
} }
@Ignore //FIXME 2.0.0 @Ignore // FIXME 2.0.0
@Test public void should_find_a_collaborator_via_load_balanced_rest_template_by_using_its_alias_from_dependencies() { @Test
public void should_find_a_collaborator_via_load_balanced_rest_template_by_using_its_alias_from_dependencies() {
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
return callingServiceAtBeansEndpointIsNotEmpty(); return callingServiceAtBeansEndpointIsNotEmpty();
} }
}); });
} }
@Ignore //FIXME 2.0.0 @Ignore // FIXME 2.0.0
@Test public void should_find_a_collaborator_using_feign_by_using_its_alias_from_dependencies() { @Test
public void should_find_a_collaborator_using_feign_by_using_its_alias_from_dependencies() {
// given: // given:
final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient; final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient;
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
then(aliasUsingFeignClient.getBeans()).isNotEmpty(); then(aliasUsingFeignClient.getBeans()).isNotEmpty();
return true; return true;
} }
}); });
} }
@Test public void should_have_headers_from_dependencies_attached_to_the_request_via_load_balanced_rest_template() { @Test
public void should_have_headers_from_dependencies_attached_to_the_request_via_load_balanced_rest_template() {
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
callingServiceToCheckIfHeadersArePassed(); callingServiceToCheckIfHeadersArePassed();
return true; return true;
} }
}); });
} }
@Ignore //FIXME 2.0.0 @Ignore // FIXME 2.0.0
@Test public void should_have_headers_from_dependencies_attached_to_the_request_via_feign() { @Test
public void should_have_headers_from_dependencies_attached_to_the_request_via_feign() {
// given: // given:
final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient; final AliasUsingFeignClient aliasUsingFeignClient = this.aliasUsingFeignClient;
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
aliasUsingFeignClient.checkHeaders(); aliasUsingFeignClient.checkHeaders();
return true; return true;
} }
}); });
} }
@Test public void should_find_a_collaborator_via_discovery_client() { @Test
public void should_find_a_collaborator_via_discovery_client() {
// // given: // // given:
final DiscoveryClient discoveryClient = this.discoveryClient; final DiscoveryClient discoveryClient = this.discoveryClient;
List<ServiceInstance> instances = discoveryClient.getInstances("someAlias"); List<ServiceInstance> instances = discoveryClient.getInstances("someAlias");
final ServiceInstance instance = instances.get(0); final ServiceInstance instance = instances.get(0);
// expect: // expect:
await().until(new Callable<Boolean>() { await().until(new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
return callingServiceViaUrlOnBeansEndpointIsNotEmpty(instance); return callingServiceViaUrlOnBeansEndpointIsNotEmpty(instance);
} }
}); });
} }
@Test public void should_have_path_equal_to_prefixed_alias() { @Test
public void should_have_path_equal_to_prefixed_alias() {
// given: // given:
ZookeeperDependency dependency = this.zookeeperDependencies.getDependencyForAlias("aliasIsPath"); ZookeeperDependency dependency = this.zookeeperDependencies
.getDependencyForAlias("aliasIsPath");
// expect: // expect:
then(dependency.getPath()).isEqualTo("/aliasIsPath"); then(dependency.getPath()).isEqualTo("/aliasIsPath");
} }
@Test public void should_have_prefixed_alias_equal_to_path() { @Test
public void should_have_prefixed_alias_equal_to_path() {
// given: // given:
ZookeeperDependency dependency = this.zookeeperDependencies.getDependencyForPath("/aliasIsPath"); ZookeeperDependency dependency = this.zookeeperDependencies
.getDependencyForPath("/aliasIsPath");
// expect: // expect:
then(dependency.getPath()).isEqualTo("/aliasIsPath"); then(dependency.getPath()).isEqualTo("/aliasIsPath");
} }
@Test public void should_have_path_set_via_string_constructor() { @Test
public void should_have_path_set_via_string_constructor() {
// given: // given:
ZookeeperDependency dependency = this.zookeeperDependencies.getDependencyForAlias("anotherAlias"); ZookeeperDependency dependency = this.zookeeperDependencies
.getDependencyForAlias("anotherAlias");
// expect: // expect:
then(dependency.getPath()).isEqualTo("/myPath"); then(dependency.getPath()).isEqualTo("/myPath");
} }
// #138 // #138
@Test public void should_parse_dependency_with_path() { @Test
public void should_parse_dependency_with_path() {
// given: // given:
StubsConfiguration someServiceStub = this.zookeeperDependencies.getDependencyForAlias("some-service").getStubsConfiguration(); StubsConfiguration someServiceStub = this.zookeeperDependencies
.getDependencyForAlias("some-service").getStubsConfiguration();
// expect: // expect:
then(someServiceStub.getStubsGroupId()).isEqualTo("io.company.department"); then(someServiceStub.getStubsGroupId()).isEqualTo("io.company.department");
then(someServiceStub.getStubsArtifactId()).isEqualTo("some-service"); then(someServiceStub.getStubsArtifactId()).isEqualTo("some-service");
@@ -162,11 +212,16 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests {
} }
private boolean callingServiceAtBeansEndpointIsNotEmpty() { private boolean callingServiceAtBeansEndpointIsNotEmpty() {
return !this.testRibbonClient.callService("someAlias", BASE_PATH + "/beans").isEmpty(); return !this.testRibbonClient.callService("someAlias", BASE_PATH + "/beans")
.isEmpty();
} }
private boolean callingServiceViaUrlOnBeansEndpointIsNotEmpty(ServiceInstance instance) { private boolean callingServiceViaUrlOnBeansEndpointIsNotEmpty(
return !this.testRibbonClient.callOnUrl(instance.getHost() + ":" + instance.getPort(), BASE_PATH + "/beans").isEmpty(); ServiceInstance instance) {
return !this.testRibbonClient
.callOnUrl(instance.getHost() + ":" + instance.getPort(),
BASE_PATH + "/beans")
.isEmpty();
} }
private void callingServiceToCheckIfHeadersArePassed() { private void callingServiceToCheckIfHeadersArePassed() {
@@ -177,5 +232,8 @@ public class ZookeeperDiscoveryWithDependenciesIntegrationTests {
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(DependencyConfig.class) @Import(DependencyConfig.class)
@Profile("dependencies") @Profile("dependencies")
static class Config { } static class Config {
}
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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; package org.springframework.cloud.zookeeper.discovery.dependency;
import java.io.Closeable; import java.io.Closeable;
@@ -11,6 +27,7 @@ import org.apache.curator.test.TestingServer;
import org.assertj.core.api.BDDAssertions; import org.assertj.core.api.BDDAssertions;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient; import org.springframework.cloud.zookeeper.discovery.test.TestRibbonClient;
@@ -28,33 +45,36 @@ import static com.jayway.awaitility.Awaitility.await;
@Ignore @Ignore
public class ZookeeperDiscoveryWithDyingDependenciesTests { public class ZookeeperDiscoveryWithDyingDependenciesTests {
private static final Log log = LogFactory.getLog(ZookeeperDiscoveryWithDyingDependenciesTests.class); private static final Log log = LogFactory
.getLog(ZookeeperDiscoveryWithDyingDependenciesTests.class);
// Issue: #45 // Issue: #45
@Test public void should_refresh_a_dependency_in_Ribbon_when_the_dependency_has_deregistered_and_registered_in_Zookeeper() @Test
public void should_refresh_a_dependency_in_Ribbon_when_the_dependency_has_deregistered_and_registered_in_Zookeeper()
throws Exception { throws Exception {
ConfigurableApplicationContext serverContext = null; ConfigurableApplicationContext serverContext = null;
ConfigurableApplicationContext clientContext = null; ConfigurableApplicationContext clientContext = null;
TestingServer testingServer = null; TestingServer testingServer = null;
try { try {
//given: // given:
int zookeeperPort = SocketUtils.findAvailableTcpPort(); int zookeeperPort = SocketUtils.findAvailableTcpPort();
testingServer = new TestingServer(zookeeperPort); testingServer = new TestingServer(zookeeperPort);
System.setProperty("spring.jmx.enabled", "false"); System.setProperty("spring.jmx.enabled", "false");
System.setProperty("spring.cloud.zookeeper.connectString", "127.0.0.1:"+zookeeperPort); System.setProperty("spring.cloud.zookeeper.connectString",
//and: "127.0.0.1:" + zookeeperPort);
// and:
serverContext = contextWithProfile("server"); serverContext = contextWithProfile("server");
clientContext = contextWithProfile("client"); clientContext = contextWithProfile("client");
//and: // and:
Integer serverPortBeforeDying = callServiceAtPortEndpoint(clientContext); Integer serverPortBeforeDying = callServiceAtPortEndpoint(clientContext);
//and: // and:
serverContext = restartContext(serverContext, "server"); serverContext = restartContext(serverContext, "server");
//expect: // expect:
await().atMost(5, TimeUnit.SECONDS).until( await().atMost(5, TimeUnit.SECONDS).until(applicationHasStartedOnANewPort(
applicationHasStartedOnANewPort(clientContext, serverPortBeforeDying) clientContext, serverPortBeforeDying));
); }
} finally { finally {
//cleanup: // cleanup:
close(serverContext); close(serverContext);
close(clientContext); close(clientContext);
close(testingServer); close(testingServer);
@@ -65,10 +85,13 @@ public class ZookeeperDiscoveryWithDyingDependenciesTests {
final ConfigurableApplicationContext clientContext, final ConfigurableApplicationContext clientContext,
final Integer serverPortBeforeDying) { final Integer serverPortBeforeDying) {
return new Callable<Boolean>() { return new Callable<Boolean>() {
@Override public Boolean call() throws Exception { @Override
public Boolean call() throws Exception {
try { try {
BDDAssertions.then(callServiceAtPortEndpoint(clientContext)).isNotEqualTo(serverPortBeforeDying); BDDAssertions.then(callServiceAtPortEndpoint(clientContext))
} catch (Exception e) { .isNotEqualTo(serverPortBeforeDying);
}
catch (Exception e) {
log.error("Exception occurred while trying to call the server", e); log.error("Exception occurred while trying to call the server", e);
return false; return false;
} }
@@ -78,26 +101,32 @@ public class ZookeeperDiscoveryWithDyingDependenciesTests {
} }
private void close(Closeable closeable) throws IOException { private void close(Closeable closeable) throws IOException {
if(closeable != null) { if (closeable != null) {
closeable.close(); closeable.close();
} }
} }
private ConfigurableApplicationContext contextWithProfile(String profile) { private ConfigurableApplicationContext contextWithProfile(String profile) {
return new SpringApplicationBuilder(Config.class).profiles(profile).build().run(); return new SpringApplicationBuilder(Config.class).profiles(profile).build().run();
} }
private ConfigurableApplicationContext restartContext(ConfigurableApplicationContext configurableApplicationContext, String profile) private ConfigurableApplicationContext restartContext(
ConfigurableApplicationContext configurableApplicationContext, String profile)
throws IOException { throws IOException {
close(configurableApplicationContext); close(configurableApplicationContext);
return contextWithProfile(profile); return contextWithProfile(profile);
} }
private Integer callServiceAtPortEndpoint(ApplicationContext applicationContext) { private Integer callServiceAtPortEndpoint(ApplicationContext applicationContext) {
return applicationContext.getBean(TestRibbonClient.class).callService("testInstance", "port", Integer.class); return applicationContext.getBean(TestRibbonClient.class)
.callService("testInstance", "port", Integer.class);
} }
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@Import(DependencyConfig.class) @Import(DependencyConfig.class)
static class Config { } static class Config {
}
} }

View File

@@ -1,6 +1,23 @@
/*
* Copyright 2015-2019 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.test; package org.springframework.cloud.zookeeper.discovery.test;
import org.apache.curator.test.TestingServer; import org.apache.curator.test.TestingServer;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.zookeeper.ZookeeperProperties; import org.springframework.cloud.zookeeper.ZookeeperProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -8,21 +25,29 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.util.SocketUtils; import org.springframework.util.SocketUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/**
*
*/
@Configuration @Configuration
public class CommonTestConfig { public class CommonTestConfig {
@Bean @Bean
@LoadBalanced RestTemplate loadBalancedRestTemplate() { @LoadBalanced
RestTemplate loadBalancedRestTemplate() {
return new RestTemplate(); return new RestTemplate();
} }
@Bean(destroyMethod = "close") TestingServer testingServer() throws Exception { @Bean(destroyMethod = "close")
TestingServer testingServer() throws Exception {
return new TestingServer(SocketUtils.findAvailableTcpPort()); return new TestingServer(SocketUtils.findAvailableTcpPort());
} }
@Bean ZookeeperProperties zookeeperProperties(TestingServer testingServer) throws Exception { @Bean
ZookeeperProperties zookeeperProperties(TestingServer testingServer)
throws Exception {
ZookeeperProperties zookeeperProperties = new ZookeeperProperties(); ZookeeperProperties zookeeperProperties = new ZookeeperProperties();
zookeeperProperties.setConnectString("localhost:" + testingServer.getPort()); zookeeperProperties.setConnectString("localhost:" + testingServer.getPort());
return zookeeperProperties; return zookeeperProperties;
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2015-2019 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.test; package org.springframework.cloud.zookeeper.discovery.test;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
@@ -23,12 +39,13 @@ public class TestRibbonClient extends TestServiceRestClient {
} }
public String thisHealthCheck() { public String thisHealthCheck() {
return this.restTemplate return this.restTemplate.getForObject(
.getForObject("http://" + this.thisAppName + BASE_PATH + "/health", String.class); "http://" + this.thisAppName + BASE_PATH + "/health", String.class);
} }
public Integer thisPort() { public Integer thisPort() {
return this.restTemplate return this.restTemplate.getForObject("http://" + this.thisAppName + "/port",
.getForObject("http://" + this.thisAppName + "/port", Integer.class); Integer.class);
} }
} }

View File

@@ -1,13 +1,31 @@
/*
* Copyright 2015-2019 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.test; package org.springframework.cloud.zookeeper.discovery.test;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* @author Marcin Grzejszczak * @author Marcin Grzejszczak
*/ */
public class TestServiceRestClient { public class TestServiceRestClient {
private static final Log log = LogFactory.getLog(TestServiceRestClient.class); private static final Log log = LogFactory.getLog(TestServiceRestClient.class);
protected final RestTemplate restTemplate; protected final RestTemplate restTemplate;
@@ -17,7 +35,7 @@ public class TestServiceRestClient {
} }
public <T> T callService(String alias, String endpoint, Class<T> clazz) { public <T> T callService(String alias, String endpoint, Class<T> clazz) {
String url = "http://" + alias +"/" + endpoint; String url = "http://" + alias + "/" + endpoint;
log.info("Calling [" + url + "]"); log.info("Calling [" + url + "]");
return this.restTemplate.getForObject(url, clazz); return this.restTemplate.getForObject(url, clazz);
} }
@@ -33,4 +51,5 @@ public class TestServiceRestClient {
return new RestTemplate().getForObject("http://" + url + endpoint, String.class); return new RestTemplate().getForObject("http://" + url + endpoint, String.class);
} }
} }

Some files were not shown because too many files have changed in this diff Show More