Merge pull request #84 from gdarmont/pr-empty-and-nested-properties-handing

* pr-empty-and-nested-properties-handing:
  Handling of empty properties and nested properties
This commit is contained in:
Spencer Gibb
2016-06-03 10:17:09 -06:00
2 changed files with 82 additions and 25 deletions

View File

@@ -43,7 +43,7 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
public ZookeeperPropertySource(String context, CuratorFramework source) {
super(context, source);
findProperties(this.getContext());
findProperties(this.getContext(), null);
}
@Override
@@ -56,8 +56,7 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
byte[] bytes = null;
try {
bytes = this.getSource().getData().forPath(fullPath);
}
catch (KeeperException e) {
} catch (KeeperException e) {
if (e.code() != KeeperException.Code.NONODE) { // not found
throw e;
}
@@ -75,31 +74,30 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
return strings.toArray(new String[strings.size()]);
}
private void findProperties(String path) {
private void findProperties(String path, List<String> children) {
try {
log.trace("entering findProperties for path: " + path);
List<String> children = null;
try {
children = this.getSource().getChildren().forPath(path);
}
catch (KeeperException e) {
if (e.code() != KeeperException.Code.NONODE) { // not found
throw e;
}
if (children == null) {
children = getChildren(path);
}
if (children == null || children.isEmpty()) {
return;
}
for (String child : children) {
String childPath = path + "/" + child;
List<String> childPathChildren = getChildren(childPath);
byte[] bytes = getPropertyBytes(childPath);
if (bytes == null || bytes.length == 0) {
findProperties(childPath);
}
else {
String key = sanitizeKey(childPath);
this.properties.put(key, new String(bytes, Charset.forName("UTF-8")));
if (childPathChildren == null || childPathChildren.isEmpty()) {
registerKeyValue(childPath, "");
}
} else {
registerKeyValue(childPath, new String(bytes, Charset.forName("UTF-8")));
}
// Check children even if we have found a value for the current znode
findProperties(childPath, childPathChildren);
}
log.trace("leaving findProperties for path: " + path);
} catch (Exception exception) {
@@ -107,4 +105,21 @@ public class ZookeeperPropertySource extends AbstractZookeeperPropertySource {
}
}
private void registerKeyValue(String path, String value) {
String key = sanitizeKey(path);
this.properties.put(key, value);
}
private List<String> getChildren(String path) throws Exception {
List<String> children = null;
try {
children = this.getSource().getChildren().forPath(path);
} catch (KeeperException e) {
if (e.code() != KeeperException.Code.NONODE) { // not found
throw e;
}
}
return children;
}
}

View File

@@ -34,7 +34,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.cloud.endpoint.RefreshEndpoint;
import org.springframework.cloud.zookeeper.ZookeeperProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -43,6 +42,7 @@ import org.springframework.util.SocketUtils;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyString;
import static org.junit.Assert.assertThat;
/**
@@ -54,7 +54,23 @@ public class ZookeeperPropertySourceLocatorTests {
public static final String PREFIX = "test__config__";
public static final String ROOT = "/" + PREFIX + UUID.randomUUID();
private ConfigurableApplicationContext context;
public static final String KEY = ROOT + "/application/testProp";
public static final String CONTEXT = ROOT + "/application/";
public static final String KEY_BASIC = "testProp";
public static final String KEY_BASIC_PATH = CONTEXT + KEY_BASIC;
public static final String VAL_BASIC = "testPropVal";
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 VAL_WITH_DOT = "withDotVal";
public static final String KEY_NESTED = "testProp.nested";
public static final String KEY_NESTED_PATH = CONTEXT + KEY_NESTED.replace('.','/');
public static final String VAL_NESTED = "nestedVal";
public static final String KEY_WITHOUT_VALUE = "testProp.novalue";
public static final String KEY_WITHOUT_VALUE_PATH = CONTEXT + KEY_WITHOUT_VALUE;
private TestingServer testingServer;
@Configuration
@@ -110,7 +126,18 @@ public class ZookeeperPropertySourceLocatorTests {
}
}
String create = this.curator.create().creatingParentsIfNeeded().forPath(KEY, "testPropVal".getBytes());
StringBuilder create = new StringBuilder(1024);
create.append(
this.curator.create().creatingParentsIfNeeded().forPath(KEY_BASIC_PATH, VAL_BASIC.getBytes())).append(
'\n');
create.append(this.curator.create().creatingParentsIfNeeded().forPath(KEY_WITH_DOT_PATH,
VAL_WITH_DOT.getBytes())).append('\n');
create.append(
this.curator.create().creatingParentsIfNeeded().forPath(KEY_NESTED_PATH, VAL_NESTED.getBytes()))
.append(
'\n');
create.append(this.curator.create().creatingParentsIfNeeded().forPath(KEY_WITHOUT_VALUE_PATH, null)).append(
'\n');
this.curator.close();
System.out.println(create);
@@ -145,17 +172,32 @@ public class ZookeeperPropertySourceLocatorTests {
}
@Test
public void propertyLoadedAndUpdated() throws Exception {
String testProp = this.environment.getProperty("testProp");
assertThat("testProp was wrong", testProp, is(equalTo("testPropVal")));
public void checkKeyValues() throws Exception {
String propValue = this.environment.getProperty(KEY_BASIC);
assertThat(KEY_BASIC + " was wrong", propValue, is(equalTo(VAL_BASIC)));
this.curator.setData().forPath(KEY, "testPropValUpdate".getBytes());
propValue = this.environment.getProperty(KEY_NESTED);
assertThat(KEY_NESTED + " was wrong", propValue, is(equalTo(VAL_NESTED)));
propValue = this.environment.getProperty(KEY_WITH_DOT);
assertThat(KEY_BASIC + " was wrong", propValue, is(equalTo(VAL_WITH_DOT)));
propValue = this.environment.getProperty(KEY_WITHOUT_VALUE);
assertThat(KEY_BASIC + " was wrong", propValue, is(isEmptyString()));
}
@Test
public void propertyLoadedAndUpdated() throws Exception {
String testProp = this.environment.getProperty(KEY_BASIC);
assertThat("testProp was wrong", testProp, is(equalTo(VAL_BASIC)));
this.curator.setData().forPath(KEY_BASIC_PATH, "testPropValUpdate".getBytes());
CountDownLatch latch = this.context.getBean(CountDownLatch.class);
boolean receivedEvent = latch.await(15, TimeUnit.SECONDS);
assertThat("listener didn't receive event", receivedEvent, is(true));
testProp = this.environment.getProperty("testProp");
testProp = this.environment.getProperty(KEY_BASIC);
assertThat("testProp was wrong after update", testProp, is(equalTo("testPropValUpdate")));
}
}