Ignore nested with NoUnboundElementsBindHandler
Update `NoUnboundElementsBindHandler` to also support ignoring nested properties. This change is required to allow the `NoUnboundElementsBindHandler` to be used alongside the `IgnoreNestedPropertiesBindHandler`. See gh-9000
This commit is contained in:
@@ -411,7 +411,8 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
||||
handler = new IgnoreErrorsBindHandler(handler);
|
||||
}
|
||||
if (!annotation.ignoreUnknownFields()) {
|
||||
handler = new NoUnboundElementsBindHandler(handler);
|
||||
handler = new NoUnboundElementsBindHandler(handler,
|
||||
annotation.ignoreNestedProperties());
|
||||
}
|
||||
if (annotation.ignoreNestedProperties()) {
|
||||
handler = new IgnoreNestedPropertiesBindHandler(handler);
|
||||
|
||||
@@ -40,14 +40,28 @@ import org.springframework.boot.context.properties.source.IterableConfigurationP
|
||||
*/
|
||||
public class NoUnboundElementsBindHandler extends AbstractBindHandler {
|
||||
|
||||
private final boolean ignoreNested;
|
||||
|
||||
private final Set<ConfigurationPropertyName> boundNames = new HashSet<>();
|
||||
|
||||
public NoUnboundElementsBindHandler() {
|
||||
super();
|
||||
this.ignoreNested = false;
|
||||
}
|
||||
|
||||
public NoUnboundElementsBindHandler(boolean ignoreNested) {
|
||||
super();
|
||||
this.ignoreNested = ignoreNested;
|
||||
}
|
||||
|
||||
public NoUnboundElementsBindHandler(BindHandler parent) {
|
||||
super(parent);
|
||||
this.ignoreNested = false;
|
||||
}
|
||||
|
||||
public NoUnboundElementsBindHandler(BindHandler parent, boolean ignoreNested) {
|
||||
super(parent);
|
||||
this.ignoreNested = ignoreNested;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +110,11 @@ public class NoUnboundElementsBindHandler extends AbstractBindHandler {
|
||||
|
||||
private boolean isUnbound(ConfigurationPropertyName name,
|
||||
ConfigurationPropertyName candidate) {
|
||||
return name.isAncestorOf(candidate) && !this.boundNames.contains(candidate);
|
||||
boolean isParent = candidate.getParent() != null
|
||||
&& name.equals(candidate.getParent());
|
||||
boolean isAncestor = name.isAncestorOf(candidate);
|
||||
return ((this.ignoreNested ? isParent : isAncestor)
|
||||
&& !this.boundNames.contains(candidate));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -103,6 +103,37 @@ public class NoUnboundElementsBindHandlerTests {
|
||||
assertThat(bound.getFoo()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindWhenUsingNoUnboundElementsHandlerIgnoreNestedAndUnboundChildShouldThrowException()
|
||||
throws Exception {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("example.foo", "bar");
|
||||
source.put("example.baz", "bar");
|
||||
this.sources.add(source);
|
||||
this.binder = new Binder(this.sources);
|
||||
try {
|
||||
this.binder.bind("example", Bindable.of(Example.class),
|
||||
new NoUnboundElementsBindHandler(true));
|
||||
fail("did not throw");
|
||||
}
|
||||
catch (BindException ex) {
|
||||
assertThat(ex.getCause().getMessage())
|
||||
.contains("The elements [example.baz] were left unbound");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindWhenUsingNoUnboundElementsHandlerIgnoreNestedAndUnboundGrandchildShouldBind()
|
||||
throws Exception {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("example.foo", "bar");
|
||||
source.put("example.foo.baz", "bar");
|
||||
this.sources.add(source);
|
||||
this.binder = new Binder(this.sources);
|
||||
this.binder.bind("example", Bindable.of(Example.class),
|
||||
new NoUnboundElementsBindHandler(true));
|
||||
}
|
||||
|
||||
public static class Example {
|
||||
|
||||
private String foo;
|
||||
|
||||
Reference in New Issue
Block a user