Reflect each source's values in env endpoint's response

Previously, the env endpoint would use the entire environment to
get the value of each property in a source. This meant that when
there were multiple sources with the same property, the value from
the source with the highest precedence would be used for every
source that contains the property.

This commit update the endpoint to retrieve the value from the
property source that is being described, rather than resolving it
against all the environment's property sources.

Closes gh-10883
This commit is contained in:
Andy Wilkinson
2017-11-23 12:58:48 +00:00
parent 5cf2e76377
commit 276a9a0eec
2 changed files with 23 additions and 1 deletions

View File

@@ -69,7 +69,9 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
Map<String, Object> properties = new LinkedHashMap<String, Object>();
for (String name : enumerable.getPropertyNames()) {
Object resolved = resolver.getProperty(name, Object.class);
Object property = source.getProperty(name);
Object resolved = property instanceof String
? resolver.resolvePlaceholders((String) property) : property;
properties.put(name, sanitize(name, resolved));
}
properties = postProcessSourceProperties(sourceName, properties);

View File

@@ -279,6 +279,26 @@ public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentE
assertThat(foo.get("bar")).isEqualTo("baz");
}
@SuppressWarnings("unchecked")
@Test
public void multipleSourcesWithSameProperty() {
this.context = new AnnotationConfigApplicationContext();
MutablePropertySources propertySources = this.context.getEnvironment()
.getPropertySources();
propertySources.addFirst(new MapPropertySource("one",
Collections.<String, Object>singletonMap("a", "alpha")));
propertySources.addFirst(new MapPropertySource("two",
Collections.<String, Object>singletonMap("a", "apple")));
this.context.register(Config.class);
this.context.refresh();
EnvironmentEndpoint report = getEndpointBean();
Map<String, Object> env = report.invoke();
Map<String, Object> sourceOne = (Map<String, Object>) env.get("one");
assertThat(sourceOne).containsEntry("a", "alpha");
Map<String, Object> sourceTwo = (Map<String, Object>) env.get("two");
assertThat(sourceTwo).containsEntry("a", "apple");
}
private void clearSystemProperties(String... properties) {
for (String property : properties) {
System.clearProperty(property);