Improve diagnostics for map binding failures
Closes gh-30281
This commit is contained in:
parent
ffe0ec6d4d
commit
ce788657ce
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -61,6 +61,7 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
|
||||||
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
|
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
|
||||||
ConfigurationProperty property = source.getConfigurationProperty(name);
|
ConfigurationProperty property = source.getConfigurationProperty(name);
|
||||||
if (property != null && !hasDescendants) {
|
if (property != null && !hasDescendants) {
|
||||||
|
getContext().setConfigurationProperty(property);
|
||||||
return getContext().getConverter().convert(property.getValue(), target);
|
return getContext().getConverter().convert(property.getValue(), target);
|
||||||
}
|
}
|
||||||
source = source.filter(name::isAncestorOf);
|
source = source.filter(name::isAncestorOf);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2021 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||||
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.springframework.core.env.MutablePropertySources;
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
|
@ -89,6 +90,16 @@ class BindFailureAnalyzerTests {
|
||||||
"failed to convert java.lang.String to java.lang.Class<?> (caused by java.lang.ClassNotFoundException: com.example.Missing"));
|
"failed to convert java.lang.String to java.lang.Class<?> (caused by java.lang.ClassNotFoundException: com.example.Missing"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bindExceptionDueToMapConversionFailure() {
|
||||||
|
FailureAnalysis analysis = performAnalysis(LoggingLevelFailureConfiguration.class, "logging.level=debug");
|
||||||
|
assertThat(analysis.getDescription()).contains(failure("logging.level", "debug",
|
||||||
|
"\"logging.level\" from property source \"test\"",
|
||||||
|
"org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting "
|
||||||
|
+ "from type [java.lang.String] to type [java.util.Map<java.lang.String, "
|
||||||
|
+ "org.springframework.boot.logging.LogLevel>]"));
|
||||||
|
}
|
||||||
|
|
||||||
private static String failure(String property, String value, String origin, String reason) {
|
private static String failure(String property, String value, String origin, String reason) {
|
||||||
return String.format("Property: %s%n Value: %s%n Origin: %s%n Reason: %s", property, value, origin,
|
return String.format("Property: %s%n Value: %s%n Origin: %s%n Reason: %s", property, value, origin,
|
||||||
reason);
|
reason);
|
||||||
|
@ -151,6 +162,11 @@ class BindFailureAnalyzerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableConfigurationProperties(LoggingProperties.class)
|
||||||
|
static class LoggingLevelFailureConfiguration {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ConfigurationProperties("test.foo")
|
@ConfigurationProperties("test.foo")
|
||||||
@Validated
|
@Validated
|
||||||
static class FieldValidationFailureProperties {
|
static class FieldValidationFailureProperties {
|
||||||
|
@ -238,6 +254,21 @@ class BindFailureAnalyzerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConfigurationProperties("logging")
|
||||||
|
static class LoggingProperties {
|
||||||
|
|
||||||
|
private Map<String, LogLevel> level = new HashMap<>();
|
||||||
|
|
||||||
|
Map<String, LogLevel> getLevel() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLevel(Map<String, LogLevel> level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
enum Fruit {
|
enum Fruit {
|
||||||
|
|
||||||
APPLE, BANANA, ORANGE
|
APPLE, BANANA, ORANGE
|
||||||
|
|
Loading…
Reference in New Issue