Skip to content

Commit

Permalink
Short circuit validation in bind handler if previous exception present
Browse files Browse the repository at this point in the history
  • Loading branch information
mbhave committed Jan 10, 2020
1 parent 7f0573d commit 1399954
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@

package org.springframework.boot.context.properties.bind.validation;

import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -52,7 +50,7 @@ public class ValidationBindHandler extends AbstractBindHandler {

private final Set<ConfigurationProperty> boundProperties = new LinkedHashSet<>();

private final Deque<BindValidationException> exceptions = new LinkedList<>();
private BindValidationException exception;

public ValidationBindHandler(Validator... validators) {
this.validators = validators;
Expand Down Expand Up @@ -94,7 +92,7 @@ private void clear() {
this.boundTypes.clear();
this.boundResults.clear();
this.boundProperties.clear();
this.exceptions.clear();
this.exception = null;
}

@Override
Expand All @@ -105,13 +103,15 @@ public void onFinish(ConfigurationPropertyName name, Bindable<?> target, BindCon
}

private void validate(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
Object validationTarget = getValidationTarget(target, context, result);
Class<?> validationType = target.getBoxedType().resolve();
if (validationTarget != null) {
validateAndPush(name, validationTarget, validationType);
if (this.exception == null) {
Object validationTarget = getValidationTarget(target, context, result);
Class<?> validationType = target.getBoxedType().resolve();
if (validationTarget != null) {
validateAndPush(name, validationTarget, validationType);
}
}
if (context.getDepth() == 0 && !this.exceptions.isEmpty()) {
throw this.exceptions.pop();
if (context.getDepth() == 0 && this.exception != null) {
throw this.exception;
}
}

Expand All @@ -134,7 +134,7 @@ private void validateAndPush(ConfigurationPropertyName name, Object target, Clas
}
}
if (result != null && result.hasErrors()) {
this.exceptions.push(new BindValidationException(result.getValidationErrors()));
this.exception = new BindValidationException(result.getValidationErrors());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,15 @@ void validationErrorsForCamelCaseFieldsShouldContainRejectedValue() {
assertThat(cause.getMessage()).contains("rejected value [2]");
}

@Test
void validationShouldBeSkippedIfPreviousValidationErrorPresent() {
this.sources.add(new MockConfigurationPropertySource("foo.inner.person-age", 2));
BindValidationException cause = bindAndExpectValidationError(() -> this.binder
.bind(ConfigurationPropertyName.of("foo"), Bindable.of(ExampleCamelCase.class), this.handler));
FieldError fieldError = (FieldError) cause.getValidationErrors().getAllErrors().get(0);
assertThat(fieldError.getField()).isEqualTo("personAge");
}

private BindValidationException bindAndExpectValidationError(Runnable action) {
try {
action.run();
Expand Down

0 comments on commit 1399954

Please sign in to comment.