Skip to content

Commit

Permalink
Use unique names for wildcard property sources
Browse files Browse the repository at this point in the history
Update `StandardConfigDataLoader` to use unique names for property
sources imported from a wildcard location.

Prior to this commit, all the property sources created from the same
wildcard location would have the same name. Each time a property source
that is equal to an existing property source is added, it replaces the
existing property source. Property source equality is name-based so this
resulted in the last property sources from the wildcard location
winning.

This commit updates `StandardConfigDataLoader` to use the resolved
Resource rather than the wildcard location in which it was discovered
in the name of the property source that it creates, ensuring that each
is property source from a wildcard location is uniquely named.

Fixes gh-24428
  • Loading branch information
wilkinsona authored and philwebb committed Dec 10, 2020
1 parent aaaed07 commit 32e1289
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 9 deletions.
Expand Up @@ -40,7 +40,7 @@ public ConfigData load(ConfigDataLoaderContext context, StandardConfigDataResour
StandardConfigDataReference reference = resource.getReference();
Resource originTrackedResource = OriginTrackedResource.of(resource.getResource(),
Origin.from(reference.getConfigDataLocation()));
String name = String.format("Config resource '%s' via location '%s'", reference.getResourceLocation(),
String name = String.format("Config resource '%s' via location '%s'", resource,
reference.getConfigDataLocation());
List<PropertySource<?>> propertySources = reference.getPropertySourceLoader().load(name, originTrackedResource);
return new ConfigData(propertySources);
Expand Down
Expand Up @@ -383,8 +383,8 @@ void runWhenHasActiveProfileConfigurationInMultiDocumentFileLoadsInExpectedOrder
List<String> names = StreamSupport.stream(context.getEnvironment().getPropertySources().spliterator(), false)
.map(org.springframework.core.env.PropertySource::getName).collect(Collectors.toList());
assertThat(names).contains(
"Config resource 'classpath:configdata/profiles/testsetprofiles.yml' via location 'classpath:configdata/profiles/' (document #0)",
"Config resource 'classpath:configdata/profiles/testsetprofiles.yml' via location 'classpath:configdata/profiles/' (document #1)");
"Config resource 'class path resource [configdata/profiles/testsetprofiles.yml]' via location 'classpath:configdata/profiles/' (document #0)",
"Config resource 'class path resource [configdata/profiles/testsetprofiles.yml]' via location 'classpath:configdata/profiles/' (document #1)");
}

@Test
Expand All @@ -411,7 +411,7 @@ void loadWhenHasConfigLocationAsFile() {
String location = "file:src/test/resources/specificlocation.properties";
ConfigurableApplicationContext context = this.application.run("--spring.config.location=" + location);
assertThat(context.getEnvironment()).has(matchingPropertySource(
"Config resource 'file:src/test/resources/specificlocation.properties' via location '" + location
"Config resource 'file [src/test/resources/specificlocation.properties]' via location '" + location
+ "'"));
}

Expand All @@ -420,7 +420,8 @@ void loadWhenHasRelativeConfigLocationUsesFileLocation() {
String location = "src/test/resources/specificlocation.properties";
ConfigurableApplicationContext context = this.application.run("--spring.config.location=" + location);
assertThat(context.getEnvironment()).has(matchingPropertySource(
"Config resource 'src/test/resources/specificlocation.properties' via location '" + location + "'"));
"Config resource 'file [src/test/resources/specificlocation.properties]' via location '" + location
+ "'"));
}

@Test
Expand Down Expand Up @@ -619,6 +620,16 @@ public Object onSuccess(ConfigurationPropertyName name, Bindable<?> target, Bind
assertThat(origin.getParent().toString()).contains("application-import-with-placeholder");
}

@Test
void runWhenHasWildcardLocationLoadsFromAllMatchingLocations() {
ConfigurableApplicationContext context = this.application.run(
"--spring.config.location=optional:file:src/test/resources/config/*/",
"--spring.config.name=testproperties");
ConfigurableEnvironment environment = context.getEnvironment();
assertThat(environment.getProperty("first.property")).isEqualTo("apple");
assertThat(environment.getProperty("second.property")).isEqualTo("ball");
}

private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {

Expand Down
Expand Up @@ -51,11 +51,13 @@ void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throw
assertThat(configData.getPropertySources().size()).isEqualTo(2);
PropertySource<?> source1 = configData.getPropertySources().get(0);
PropertySource<?> source2 = configData.getPropertySources().get(1);
assertThat(source1.getName()).isEqualTo("Config resource 'classpath:configdata/yaml/application.yml' "
+ "via location 'classpath:configdata/yaml/application.yml' (document #0)");
assertThat(source1.getName())
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
+ "via location 'classpath:configdata/yaml/application.yml' (document #0)");
assertThat(source1.getProperty("foo")).isEqualTo("bar");
assertThat(source2.getName()).isEqualTo("Config resource 'classpath:configdata/yaml/application.yml' "
+ "via location 'classpath:configdata/yaml/application.yml' (document #1)");
assertThat(source2.getName())
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
+ "via location 'classpath:configdata/yaml/application.yml' (document #1)");
assertThat(source2.getProperty("hello")).isEqualTo("world");
}

Expand Down

0 comments on commit 32e1289

Please sign in to comment.