From 459338f6fd19c3668714d79d18994a4921cba407 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Thu, 21 Dec 2023 17:55:49 +0000 Subject: [PATCH] Unwrap Optional in MethodValidationAdapter See gh-31746 --- .../MethodValidationAdapter.java | 5 +++++ ...hodValidationAdapterPropertyPathTests.java | 20 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) 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 17e320ed0666..da156f85c731 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 @@ -24,6 +24,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; @@ -354,6 +355,10 @@ else if (containerKey != null && arg instanceof Map map) { bean = map.get(containerKey); container = map; } + else if (arg instanceof Optional optional) { + bean = optional.orElse(null); + container = optional; + } else { Assert.state(!node.isInIterable(), "No way to unwrap Iterable without index"); bean = arg; diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterPropertyPathTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterPropertyPathTests.java index 04a09463e235..45614621d50d 100644 --- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterPropertyPathTests.java +++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationAdapterPropertyPathTests.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; @@ -146,6 +147,20 @@ void fieldOfObjectPropertyOfMapValue() { assertSingleFieldError(errors, 1, courses, null, "CS 101", "professor.name", invalidPerson.name()); } + @Test + void fieldOfObjectPropertyOfOptionalBean() { + Method method = getMethod("addOptionalCourse"); + Optional optional = Optional.of(new Course("CS 101", invalidPerson, Collections.emptyList())); + Object[] args = {optional}; + + MethodValidationResult result = + validationAdapter.validateArguments(new MyService(), method, null, args, HINTS); + + assertThat(result.getAllErrors()).hasSize(1); + ParameterErrors errors = result.getBeanResults().get(0); + assertSingleFieldError(errors, 1, optional, null, null, "professor.name", invalidPerson.name()); + } + } @@ -204,7 +219,7 @@ private static Method getMethod(String methodName) { } - @SuppressWarnings("unused") + @SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"}) private static class MyService { public void addCourse(@Valid Course course) { @@ -219,6 +234,9 @@ public void addCourseArray(@Valid Course[] courses) { public void addCourseMap(@Valid Map courses) { } + public void addOptionalCourse(@Valid Optional course) { + } + @Valid public Course getCourse(Course course) { throw new UnsupportedOperationException();