Validate onFailure returned binding results
Update `ValidationBindHandler` so that any non-null result returned by the parent `onFailure` method triggers re-validation. Fixes gh-17421
This commit is contained in:
parent
d641a1e23a
commit
cd5f40aec2
|
|
@ -76,7 +76,10 @@ public class ValidationBindHandler extends AbstractBindHandler {
|
||||||
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Exception error)
|
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Exception error)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Object result = super.onFailure(name, target, context, error);
|
Object result = super.onFailure(name, target, context, error);
|
||||||
validate(name, target, context, null);
|
if (result != null) {
|
||||||
|
this.exceptions.clear();
|
||||||
|
}
|
||||||
|
validate(name, target, context, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ public class ValidationBindHandlerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindShouldValidateIfOtherHandlersInChainIgnoreError() {
|
public void bindShouldValidateIfOtherHandlersInChainIgnoreError() {
|
||||||
TestHandler testHandler = new TestHandler();
|
TestHandler testHandler = new TestHandler(null);
|
||||||
this.handler = new ValidationBindHandler(testHandler, this.validator);
|
this.handler = new ValidationBindHandler(testHandler, this.validator);
|
||||||
this.sources.add(new MockConfigurationPropertySource("foo", "hello"));
|
this.sources.add(new MockConfigurationPropertySource("foo", "hello"));
|
||||||
ExampleValidatedBean bean = new ExampleValidatedBean();
|
ExampleValidatedBean bean = new ExampleValidatedBean();
|
||||||
|
|
@ -177,6 +177,21 @@ public class ValidationBindHandlerTests {
|
||||||
.withCauseInstanceOf(BindValidationException.class);
|
.withCauseInstanceOf(BindValidationException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bindShouldValidateIfOtherHandlersInChainReplaceErrorWithResult() {
|
||||||
|
TestHandler testHandler = new TestHandler(new ExampleValidatedBeanSubclass());
|
||||||
|
this.handler = new ValidationBindHandler(testHandler, this.validator);
|
||||||
|
this.sources.add(new MockConfigurationPropertySource("foo", "hello"));
|
||||||
|
this.sources.add(new MockConfigurationPropertySource("foo.age", "bad"));
|
||||||
|
this.sources.add(new MockConfigurationPropertySource("foo.years", "99"));
|
||||||
|
ExampleValidatedBean bean = new ExampleValidatedBean();
|
||||||
|
assertThatExceptionOfType(BindException.class)
|
||||||
|
.isThrownBy(() -> this.binder.bind("foo",
|
||||||
|
Bindable.of(ExampleValidatedBean.class).withExistingValue(bean), this.handler))
|
||||||
|
.withCauseInstanceOf(BindValidationException.class)
|
||||||
|
.satisfies((ex) -> assertThat(ex.getCause()).hasMessageContaining("years"));
|
||||||
|
}
|
||||||
|
|
||||||
private BindValidationException bindAndExpectValidationError(Runnable action) {
|
private BindValidationException bindAndExpectValidationError(Runnable action) {
|
||||||
try {
|
try {
|
||||||
action.run();
|
action.run();
|
||||||
|
|
@ -219,6 +234,25 @@ public class ValidationBindHandlerTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ExampleValidatedBeanSubclass extends ExampleValidatedBean {
|
||||||
|
|
||||||
|
@Min(100)
|
||||||
|
private int years;
|
||||||
|
|
||||||
|
public ExampleValidatedBeanSubclass() {
|
||||||
|
setAge(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYears() {
|
||||||
|
return this.years;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYears(int years) {
|
||||||
|
this.years = years;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Validated
|
@Validated
|
||||||
public static class ExampleValidatedWithNestedBean {
|
public static class ExampleValidatedWithNestedBean {
|
||||||
|
|
||||||
|
|
@ -282,10 +316,16 @@ public class ValidationBindHandlerTests {
|
||||||
|
|
||||||
static class TestHandler extends AbstractBindHandler {
|
static class TestHandler extends AbstractBindHandler {
|
||||||
|
|
||||||
|
private Object result;
|
||||||
|
|
||||||
|
TestHandler(Object result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context,
|
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context,
|
||||||
Exception error) throws Exception {
|
Exception error) throws Exception {
|
||||||
return null;
|
return this.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue