Merge branch '3.3.x'
Closes gh-43382
This commit is contained in:
@@ -16,16 +16,18 @@
|
||||
|
||||
package org.springframework.boot.diagnostics.analyzer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
import org.springframework.boot.diagnostics.FailureAnalyzer;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.boot.origin.PropertySourceOrigin;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
@@ -61,18 +63,23 @@ class InvalidConfigurationPropertyValueFailureAnalyzer
|
||||
}
|
||||
|
||||
private List<Descriptor> getDescriptors(String propertyName) {
|
||||
Set<Origin> seen = new HashSet<>();
|
||||
return getPropertySources().filter((source) -> source.containsProperty(propertyName))
|
||||
.map((source) -> Descriptor.get(source, propertyName))
|
||||
.filter((descriptor) -> seen.add(getOrigin(descriptor)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> getPropertySources() {
|
||||
if (this.environment == null) {
|
||||
return Stream.empty();
|
||||
private Origin getOrigin(Descriptor descriptor) {
|
||||
Origin origin = descriptor.origin;
|
||||
if (origin instanceof PropertySourceOrigin propertySourceOrigin) {
|
||||
origin = propertySourceOrigin.getOrigin();
|
||||
}
|
||||
return this.environment.getPropertySources()
|
||||
.stream()
|
||||
.filter((source) -> !ConfigurationPropertySources.isAttachedConfigurationPropertySource(source));
|
||||
return origin;
|
||||
}
|
||||
|
||||
private Stream<PropertySource<?>> getPropertySources() {
|
||||
return (this.environment != null) ? this.environment.getPropertySources().stream() : Stream.empty();
|
||||
}
|
||||
|
||||
private void appendDetails(StringBuilder message, InvalidConfigurationPropertyValueException cause,
|
||||
|
||||
@@ -20,13 +20,16 @@ import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -63,6 +66,26 @@ class InvalidConfigurationPropertyValueFailureAnalyzerTests {
|
||||
.doesNotContain("Additionally, this property is also set");
|
||||
}
|
||||
|
||||
@Test
|
||||
void analysisWithKnownPropertyFromSystemEnvironment() {
|
||||
MapPropertySource source = new SystemEnvironmentPropertySource("systemEnvironment",
|
||||
Collections.singletonMap("COM_EXAMPLE_TESTPROPERTY", "invalid"));
|
||||
this.environment.getPropertySources().addFirst(source);
|
||||
ConfigurationPropertySources.attach(this.environment);
|
||||
assertThat(this.environment.getProperty("com.example.test-property")).isEqualTo("invalid");
|
||||
InvalidConfigurationPropertyValueException failure = new InvalidConfigurationPropertyValueException(
|
||||
"com.example.test-property", "invalid", "This is not valid.");
|
||||
FailureAnalysis analysis = performAnalysis(failure);
|
||||
assertThat(analysis.getDescription()).contains("com.example.test-property")
|
||||
.contains("invalid")
|
||||
.contains("property source \"systemEnvironment\"");
|
||||
assertThat(analysis.getCause()).isSameAs(failure);
|
||||
assertThat(analysis.getAction()).contains("Review the value of the property with the provided reason.");
|
||||
assertThat(analysis.getDescription()).contains("Validation failed for the following reason")
|
||||
.contains("This is not valid.")
|
||||
.doesNotContain("Additionally, this property is also set");
|
||||
}
|
||||
|
||||
@Test
|
||||
void analysisWithKnownPropertyAndNoReason() {
|
||||
MapPropertySource source = new MapPropertySource("test", Collections.singletonMap("test.property", "invalid"));
|
||||
@@ -84,6 +107,8 @@ class InvalidConfigurationPropertyValueFailureAnalyzerTests {
|
||||
this.environment.getPropertySources().addFirst(OriginCapablePropertySource.get(source));
|
||||
this.environment.getPropertySources().addLast(additional);
|
||||
this.environment.getPropertySources().addLast(OriginCapablePropertySource.get(another));
|
||||
this.environment.getPropertySources().addLast(OriginCapablePropertySource.get("another-again", another));
|
||||
ConfigurationPropertySources.attach(this.environment);
|
||||
InvalidConfigurationPropertyValueException failure = new InvalidConfigurationPropertyValueException(
|
||||
"test.property", "invalid", "This is not valid.");
|
||||
FailureAnalysis analysis = performAnalysis(failure);
|
||||
@@ -92,7 +117,8 @@ class InvalidConfigurationPropertyValueFailureAnalyzerTests {
|
||||
assertThat(analysis.getDescription())
|
||||
.contains("Additionally, this property is also set in the following property sources:")
|
||||
.contains("In 'additional' with the value 'valid'")
|
||||
.contains("In 'another' with the value 'test' (originating from 'TestOrigin test.property')");
|
||||
.contains("In 'another' with the value 'test' (originating from 'TestOrigin test.property')")
|
||||
.doesNotContain("another-again");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,7 +148,11 @@ class InvalidConfigurationPropertyValueFailureAnalyzerTests {
|
||||
private final EnumerablePropertySource<T> propertySource;
|
||||
|
||||
OriginCapablePropertySource(EnumerablePropertySource<T> propertySource) {
|
||||
super(propertySource.getName(), propertySource.getSource());
|
||||
this(propertySource.getName(), propertySource);
|
||||
}
|
||||
|
||||
OriginCapablePropertySource(String name, EnumerablePropertySource<T> propertySource) {
|
||||
super(name, propertySource.getSource());
|
||||
this.propertySource = propertySource;
|
||||
}
|
||||
|
||||
@@ -138,20 +168,53 @@ class InvalidConfigurationPropertyValueFailureAnalyzerTests {
|
||||
|
||||
@Override
|
||||
public Origin getOrigin(String name) {
|
||||
return new Origin() {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestOrigin " + name;
|
||||
}
|
||||
|
||||
};
|
||||
return new TestOrigin(name, this.propertySource.getName());
|
||||
}
|
||||
|
||||
static <T> OriginCapablePropertySource<T> get(EnumerablePropertySource<T> propertySource) {
|
||||
return new OriginCapablePropertySource<>(propertySource);
|
||||
}
|
||||
|
||||
static <T> OriginCapablePropertySource<T> get(String name, EnumerablePropertySource<T> propertySource) {
|
||||
return new OriginCapablePropertySource<>(name, propertySource);
|
||||
}
|
||||
|
||||
static final class TestOrigin implements Origin {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String sourceName;
|
||||
|
||||
private TestOrigin(String name, String sourceName) {
|
||||
this.name = name;
|
||||
this.sourceName = sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TestOrigin other = (TestOrigin) obj;
|
||||
return ObjectUtils.nullSafeEquals(this.name, other.name)
|
||||
&& ObjectUtils.nullSafeEquals(this.sourceName, other.sourceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestOrigin " + this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user