Commit 14540050 authored by Phillip Webb's avatar Phillip Webb

Only validate target values on zero depth

Update `ValidationBindHandler` so that validation only occurs when a
value is bound, or the bind depth is zero. This prevents validation from
triggering getters which may throw an exception.

Fixes gh-12227
parent 32448360
...@@ -69,7 +69,7 @@ public class ValidationBindHandler extends AbstractBindHandler { ...@@ -69,7 +69,7 @@ public class ValidationBindHandler extends AbstractBindHandler {
@Override @Override
public void onFinish(ConfigurationPropertyName name, Bindable<?> target, public void onFinish(ConfigurationPropertyName name, Bindable<?> target,
BindContext context, Object result) throws Exception { BindContext context, Object result) throws Exception {
validate(name, target, result); validate(name, target, context, result);
if (context.getDepth() == 0 && !this.exceptions.isEmpty()) { if (context.getDepth() == 0 && !this.exceptions.isEmpty()) {
throw this.exceptions.pop(); throw this.exceptions.pop();
} }
...@@ -77,17 +77,18 @@ public class ValidationBindHandler extends AbstractBindHandler { ...@@ -77,17 +77,18 @@ public class ValidationBindHandler extends AbstractBindHandler {
} }
private void validate(ConfigurationPropertyName name, Bindable<?> target, private void validate(ConfigurationPropertyName name, Bindable<?> target,
Object result) { BindContext context, Object result) {
Object validationTarget = getValidationTarget(target, result); Object validationTarget = getValidationTarget(target, context, result);
Class<?> validationType = target.getBoxedType().resolve(); Class<?> validationType = target.getBoxedType().resolve();
validate(name, validationTarget, validationType); validate(name, validationTarget, validationType);
} }
private Object getValidationTarget(Bindable<?> target, Object result) { private Object getValidationTarget(Bindable<?> target, BindContext context,
Object result) {
if (result != null) { if (result != null) {
return result; return result;
} }
if (target.getValue() != null) { if (context.getDepth() == 0 && target.getValue() != null) {
return target.getValue().get(); return target.getValue().get();
} }
return null; return null;
......
...@@ -153,6 +153,19 @@ public class ValidationBindHandlerTests { ...@@ -153,6 +153,19 @@ public class ValidationBindHandlerTests {
this.handler)); this.handler));
} }
@Test
public void bindShouldNotValidateDepthGreaterThanZero() {
// gh-12227
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo.bar", "baz");
this.sources.add(source);
ExampleValidatedBeanWithGetterException existingValue = new ExampleValidatedBeanWithGetterException();
this.binder.bind(ConfigurationPropertyName.of("foo"),
Bindable.of(ExampleValidatedBeanWithGetterException.class)
.withExistingValue(existingValue),
this.handler);
}
private BindValidationException bindAndExpectValidationError(Runnable action) { private BindValidationException bindAndExpectValidationError(Runnable action) {
try { try {
action.run(); action.run();
...@@ -244,6 +257,16 @@ public class ValidationBindHandlerTests { ...@@ -244,6 +257,16 @@ public class ValidationBindHandlerTests {
public void setAddress(String address) { public void setAddress(String address) {
this.address = address; this.address = address;
} }
}
@Validated
public static class ExampleValidatedBeanWithGetterException {
public int getAge() {
throw new RuntimeException();
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment