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 fa218e5cd2..8a7f365b92 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 @@ -50,7 +50,6 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; import org.springframework.util.function.SingletonSupplier; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.BindingResult; @@ -321,7 +320,7 @@ public class MethodValidationAdapter implements MethodValidator { Object arg = argumentFunction.apply(parameter.getParameterIndex()); - // If the arg is a container, we need to element, but the only way to extract it + // If the arg is a container, we need the element, but the only way to extract it // is to check for and use a container index or key on the next node: // https://github.com/jakartaee/validation/issues/194 @@ -346,12 +345,16 @@ public class MethodValidationAdapter implements MethodValidator { value = map.get(key); container = map; } + else if (arg instanceof Iterable) { + // No index or key, cannot access the specific value + value = arg; + container = arg; + } else if (arg instanceof Optional optional) { value = optional.orElse(null); container = optional; } else { - Assert.state(!node.isInIterable(), "No way to unwrap Iterable without index"); value = arg; container = null; } diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterTests.java index 0fe51acdc9..3519210f7e 100644 --- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterTests.java +++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterTests.java @@ -19,6 +19,7 @@ package org.springframework.validation.beanvalidation; import java.lang.reflect.Method; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.function.Consumer; import jakarta.validation.Valid; @@ -201,9 +202,7 @@ class MethodValidationAdapterTests { Method method = getMethod(target, "addHobbies"); testArgs(target, method, new Object[] {List.of(" ")}, ex -> { - assertThat(ex.getAllValidationResults()).hasSize(1); - assertValueResult(ex.getValueResults().get(0), 0, " ", List.of(""" org.springframework.context.support.DefaultMessageSourceResolvable: \ codes [NotBlank.myService#addHobbies.hobbies,NotBlank.hobbies,NotBlank.java.util.List,NotBlank]; \ @@ -213,6 +212,22 @@ class MethodValidationAdapterTests { }); } + @Test // gh-33150 + void validateValueSetArgument() { + MyService target = new MyService(); + Method method = getMethod(target, "addUniqueHobbies"); + + testArgs(target, method, new Object[] {Set.of("test", " ")}, ex -> { + assertThat(ex.getAllValidationResults()).hasSize(1); + assertValueResult(ex.getValueResults().get(0), 0, Set.of("test", " "), List.of(""" + org.springframework.context.support.DefaultMessageSourceResolvable: \ + codes [NotBlank.myService#addUniqueHobbies.hobbies,NotBlank.hobbies,NotBlank.java.util.Set,NotBlank]; \ + arguments [org.springframework.context.support.DefaultMessageSourceResolvable: \ + codes [myService#addUniqueHobbies.hobbies,hobbies]; \ + arguments []; default message [hobbies]]; default message [must not be blank]""")); + }); + } + private void testArgs(Object target, Method method, Object[] args, Consumer consumer) { consumer.accept(this.validationAdapter.validateArguments(target, method, null, args, new Class[0])); } @@ -271,6 +286,8 @@ class MethodValidationAdapterTests { public void addHobbies(List<@NotBlank String> hobbies) { } + public void addUniqueHobbies(Set<@NotBlank String> hobbies) { + } }