Moves common property source functionality to ZookeeperPropertySources.java

This commit is contained in:
spencergibb
2020-09-18 17:19:22 -04:00
parent beb4873984
commit 4cf27efdbe
7 changed files with 115 additions and 89 deletions

View File

@@ -24,6 +24,8 @@ import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
/**
* Bootstrap Configuration for Zookeeper Configuration.
@@ -45,8 +47,12 @@ public class ZookeeperConfigBootstrapConfiguration {
@Bean
@ConditionalOnMissingBean
public ZookeeperConfigProperties zookeeperConfigProperties() {
return new ZookeeperConfigProperties();
public ZookeeperConfigProperties zookeeperConfigProperties(Environment env) {
ZookeeperConfigProperties properties = new ZookeeperConfigProperties();
if (StringUtils.isEmpty(properties.getName())) {
properties.setName(env.getProperty("spring.application.name", "application"));
}
return properties;
}
}

View File

@@ -18,8 +18,6 @@ package org.springframework.cloud.zookeeper.config;
import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.context.config.ConfigData;
@@ -29,8 +27,6 @@ import org.springframework.boot.context.config.ConfigDataLocationNotFoundExcepti
public class ZookeeperConfigDataLoader implements ConfigDataLoader<ZookeeperConfigDataLocation> {
private static final Log log = LogFactory.getLog(ZookeeperConfigDataLoader.class);
@Override
public ConfigData load(ConfigDataLoaderContext context, ZookeeperConfigDataLocation location) {
try {
@@ -40,16 +36,8 @@ public class ZookeeperConfigDataLoader implements ConfigDataLoader<ZookeeperConf
return new ConfigData(Collections.singletonList(propertySource));
}
catch (Exception e) {
ZookeeperConfigProperties properties = context.getBootstrapContext()
.get(ZookeeperConfigProperties.class);
if (properties.isFailFast() || !location.isOptional()) {
throw new ConfigDataLocationNotFoundException(location, e);
}
else {
log.warn("Unable to load zookeeper config from " + location.getContext(), e);
}
throw new ConfigDataLocationNotFoundException(location, e);
}
return null;
}
}

View File

@@ -25,7 +25,6 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.curator.RetryPolicy;
import org.apache.curator.drivers.TracerDriver;
import org.apache.curator.ensemble.EnsembleProvider;
@@ -51,13 +50,17 @@ import org.springframework.web.util.UriComponentsBuilder;
public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationResolver<ZookeeperConfigDataLocation> {
private static final Log log = LogFactory.getLog(ZookeeperConfigDataLocationResolver.class);
/**
* Zookeeper Config Data prefix.
*/
public static final String PREFIX = "zookeeper:";
private final Log log;
public ZookeeperConfigDataLocationResolver(Log log) {
this.log = log;
}
@Override
public boolean isResolvable(ConfigDataLocationResolverContext context, String location) {
if (!location.startsWith(PREFIX)) {
@@ -94,8 +97,10 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe
context.getBootstrapContext().registerIfAbsent(CuratorFramework.class, InstanceSupplier
.from(() -> curatorFramework(context.getBootstrapContext(), zookeeperProperties, optional)));
ZookeeperPropertySources sources = new ZookeeperPropertySources(properties, log);
List<String> contexts = (locationUri == null || CollectionUtils.isEmpty(locationUri.getPathSegments()))
? getAutomaticContexts(profiles, properties) : getCustomContexts(locationUri);
? sources.getAutomaticContexts(profiles.getAccepted()) : getCustomContexts(locationUri);
context.getBootstrapContext().addCloseListener(event -> {
CuratorFramework curatorFramework = event.getBootstrapContext().get(CuratorFramework.class);
@@ -122,27 +127,6 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe
return Arrays.asList(uriComponents.getPath().split(";"));
}
protected List<String> getAutomaticContexts(Profiles profiles, ZookeeperConfigProperties properties) {
String root = properties.getRoot();
List<String> contexts = new ArrayList<>();
String defaultContext = root + "/" + properties.getDefaultContext();
contexts.add(defaultContext);
addProfiles(contexts, defaultContext, profiles, properties);
StringBuilder baseContext = new StringBuilder(root);
if (!properties.getName().startsWith("/")) {
baseContext.append("/");
}
// getName() defaults to ${spring.application.name} or application
baseContext.append(properties.getName());
contexts.add(baseContext.toString());
addProfiles(contexts, baseContext.toString(), profiles, properties);
Collections.reverse(contexts);
return contexts;
}
@Nullable
protected UriComponents parseLocation(String location) {
String uri = location.substring(PREFIX.length());
@@ -158,13 +142,6 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe
return UriComponentsBuilder.fromUriString(uri).build();
}
private void addProfiles(List<String> contexts, String baseContext, Profiles profiles,
ZookeeperConfigProperties properties) {
for (String profile : profiles.getAccepted()) {
contexts.add(baseContext + properties.getProfileSeparator() + profile);
}
}
protected CuratorFramework curatorFramework(ConfigurableBootstrapContext context, ZookeeperProperties properties,
boolean optional) {

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.zookeeper.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -32,8 +31,7 @@ import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.Assert;
/**
* Zookeeper provides a <a href=
@@ -78,6 +76,7 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
public ZookeeperPropertySourceLocator(CuratorFramework curator,
ZookeeperConfigProperties properties) {
this.curator = curator;
Assert.hasText(properties.getName(), ZookeeperConfigProperties.PREFIX + ".name must not be empty");
this.properties = properties;
}
@@ -89,50 +88,19 @@ public class ZookeeperPropertySourceLocator implements PropertySourceLocator {
public PropertySource<?> locate(Environment environment) {
if (environment instanceof ConfigurableEnvironment) {
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
String appName = properties.getName();
if (StringUtils.isEmpty(appName)) {
// use default "application" (which config client does)
appName = env.getProperty("spring.application.name", "application");
if (appName.equals("application")) {
log.warn("spring.application.name is not set. Using default of 'application'");
}
}
List<String> profiles = Arrays.asList(env.getActiveProfiles());
String root = this.properties.getRoot();
this.contexts = new ArrayList<>();
String defaultContext = root + "/" + this.properties.getDefaultContext();
this.contexts.add(defaultContext);
addProfiles(this.contexts, defaultContext, profiles);
StringBuilder baseContext = new StringBuilder(root);
if (!appName.startsWith("/")) {
baseContext.append("/");
}
baseContext.append(appName);
this.contexts.add(baseContext.toString());
addProfiles(this.contexts, baseContext.toString(), profiles);
ZookeeperPropertySources sources = new ZookeeperPropertySources(properties, log);
this.contexts = sources.getAutomaticContexts(profiles);
CompositePropertySource composite = new CompositePropertySource("zookeeper");
Collections.reverse(this.contexts);
for (String propertySourceContext : this.contexts) {
try {
PropertySource propertySource = create(propertySourceContext);
composite.addPropertySource(propertySource);
// TODO: howto call close when /refresh
}
catch (Exception e) {
if (this.properties.isFailFast()) {
ReflectionUtils.rethrowRuntimeException(e);
}
else {
log.warn("Unable to load zookeeper config from "
+ propertySourceContext, e);
}
}
PropertySource<CuratorFramework> propertySource = sources.createPropertySource(propertySourceContext, true, this.curator);
composite.addPropertySource(propertySource);
}
return composite;

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2015-2020 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
*
* https://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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.curator.framework.CuratorFramework;
public class ZookeeperPropertySources {
private final ZookeeperConfigProperties properties;
private final Log log;
public ZookeeperPropertySources(ZookeeperConfigProperties properties, Log log) {
this.properties = properties;
this.log = log;
}
public List<String> getAutomaticContexts(List<String> profiles) {
String root = properties.getRoot();
List<String> contexts = new ArrayList<>();
String defaultContext = root + "/" + properties.getDefaultContext();
contexts.add(defaultContext);
addProfiles(contexts, defaultContext, profiles);
StringBuilder baseContext = new StringBuilder(root);
if (!properties.getName().startsWith("/")) {
baseContext.append("/");
}
// getName() defaults to ${spring.application.name} or application
baseContext.append(properties.getName());
contexts.add(baseContext.toString());
addProfiles(contexts, baseContext.toString(), profiles);
Collections.reverse(contexts);
return contexts;
}
private void addProfiles(List<String> contexts, String baseContext, List<String> profiles) {
for (String profile : profiles) {
contexts.add(baseContext + properties.getProfileSeparator() + profile);
}
}
public ZookeeperPropertySource createPropertySource(String context, boolean optional, CuratorFramework curator) {
try {
return new ZookeeperPropertySource(context, curator);
// TODO: howto call close when /refresh
}
catch (Exception e) {
if (this.properties.isFailFast() || !optional) {
throw new ZookeeperPropertySourceNotFoundException(e);
}
else {
log.warn("Unable to load zookeeper config from " + context, e);
}
}
return null;
}
static class ZookeeperPropertySourceNotFoundException extends RuntimeException {
ZookeeperPropertySourceNotFoundException(Exception source) {
super(source);
}
}
}

View File

@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
import org.springframework.boot.ConfigurableBootstrapContext;
@@ -39,7 +40,7 @@ public class ZookeeperConfigDataLocationResolverTests {
@Test
public void testParseLocation() {
ZookeeperConfigDataLocationResolver resolver = new ZookeeperConfigDataLocationResolver();
ZookeeperConfigDataLocationResolver resolver = new ZookeeperConfigDataLocationResolver(LogFactory.getLog(getClass()));
UriComponents uriComponents = resolver.parseLocation(
"zookeeper:myhost:2182/mypath1;/mypath2;/mypath3");
assertThat(uriComponents.toUri()).hasScheme("zookeeper").hasHost("myhost")
@@ -102,7 +103,7 @@ public class ZookeeperConfigDataLocationResolverTests {
}
private ZookeeperConfigDataLocationResolver createResolver() {
return new ZookeeperConfigDataLocationResolver();
return new ZookeeperConfigDataLocationResolver(LogFactory.getLog(getClass()));
}
}

View File

@@ -34,8 +34,10 @@ public class ZookeeperPropertySourceLocatorNoApplicationNameTests {
public void defaultSpringApplicationNameWorks() {
CuratorFramework curator = mock(CuratorFramework.class);
when(curator.getChildren()).thenReturn(mock(GetChildrenBuilder.class));
ZookeeperConfigProperties properties = new ZookeeperConfigProperties();
properties.setName("notempty");
ZookeeperPropertySourceLocator locator = new ZookeeperPropertySourceLocator(
curator, new ZookeeperConfigProperties());
curator, properties);
locator.locate(new MockEnvironment());
}