diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java index 022c2015c1f..128abc400e9 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationAdapter.java @@ -350,7 +350,7 @@ public class MethodValidationAdapter { private final List resolvableErrors = new ArrayList<>(); - private final Set> violations = new LinkedHashSet<>(); + private final List> violations = new ArrayList<>(); public ValueResultBuilder(Object target, MethodParameter parameter, @Nullable Object argument) { this.target = target; @@ -359,8 +359,8 @@ public class MethodValidationAdapter { } public void addViolation(ConstraintViolation violation) { - this.violations.add(violation); this.resolvableErrors.add(createMessageSourceResolvable(this.target, this.parameter, violation)); + this.violations.add(violation); } public ParameterValidationResult build() { @@ -449,8 +449,22 @@ public class MethodValidationAdapter { Integer containerIndex2 = errors2.getContainerIndex(); if (containerIndex1 != null && containerIndex2 != null) { i = Integer.compare(containerIndex1, containerIndex2); - return i; + if (i != 0) { + return i; + } } + i = compareKeys(errors1, errors2); + return i; + } + return 0; + } + + @SuppressWarnings("unchecked") + private int compareKeys(ParameterErrors errors1, ParameterErrors errors2) { + Object key1 = errors1.getContainerKey(); + Object key2 = errors2.getContainerKey(); + if (key1 instanceof Comparable && key2 instanceof Comparable) { + return ((Comparable) key1).compareTo((E) key2); } return 0; } diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterErrors.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterErrors.java index 3c7d129a95f..cae8ac5e713 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterErrors.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterErrors.java @@ -16,9 +16,8 @@ package org.springframework.validation.beanvalidation; -import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import java.util.Set; import jakarta.validation.ConstraintViolation; @@ -66,10 +65,10 @@ public class ParameterErrors extends ParameterValidationResult implements Errors */ public ParameterErrors( MethodParameter parameter, @Nullable Object argument, Errors errors, - Set> violations, + Collection> violations, @Nullable Object container, @Nullable Integer index, @Nullable Object key) { - super(parameter, argument, new ArrayList<>(errors.getAllErrors()), violations); + super(parameter, argument, errors.getAllErrors(), violations); this.errors = errors; this.container = container; diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterValidationResult.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterValidationResult.java index d38dbd73e39..d71dbdbf5d0 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterValidationResult.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/ParameterValidationResult.java @@ -16,8 +16,8 @@ package org.springframework.validation.beanvalidation; +import java.util.Collection; import java.util.List; -import java.util.Set; import jakarta.validation.ConstraintViolation; @@ -51,23 +51,24 @@ public class ParameterValidationResult { private final List resolvableErrors; - private final Set> violations; + private final List> violations; /** * Create a {@code ParameterValidationResult}. */ public ParameterValidationResult( - MethodParameter methodParameter, @Nullable Object argument, List errors, - Set> violations) { + MethodParameter methodParameter, @Nullable Object argument, + Collection resolvableErrors, + Collection> violations) { - Assert.notNull(methodParameter, "`MethodParameter` is required"); - Assert.notEmpty(errors, "`resolvableErrors` must not be empty"); + Assert.notNull(methodParameter, "MethodParameter is required"); + Assert.notEmpty(resolvableErrors, "`resolvableErrors` must not be empty"); Assert.notEmpty(violations, "'violations' must not be empty"); this.methodParameter = methodParameter; this.argument = argument; - this.resolvableErrors = List.copyOf(errors); - this.violations = violations; + this.resolvableErrors = List.copyOf(resolvableErrors); + this.violations = List.copyOf(violations); } @@ -110,9 +111,10 @@ public class ParameterValidationResult { } /** - * The violations associated with the method parameter. + * The violations associated with the method parameter, in the same order + * as {@link #getResolvableErrors()}. */ - public Set> getViolations() { + public List> getViolations() { return this.violations; }