From d4719493bde4bc75c772edae2e241a563609a77b Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 6 Nov 2024 14:10:45 +0000 Subject: [PATCH] Empty string check after conversion in AbstractNamedValueArgumentResolver Closes gh-33794 --- .../invoker/AbstractNamedValueArgumentResolver.java | 5 +++++ .../service/invoker/NamedValueArgumentResolverTests.java | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/AbstractNamedValueArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/service/invoker/AbstractNamedValueArgumentResolver.java index 238a5e858626..3a967ed0c7d4 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/AbstractNamedValueArgumentResolver.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/AbstractNamedValueArgumentResolver.java @@ -32,6 +32,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ValueConstants; /** @@ -191,11 +192,15 @@ private void addSingleValue( } if (this.conversionService != null && !(value instanceof String)) { + Object beforeValue = value; parameter = parameter.nestedIfOptional(); Class type = parameter.getNestedParameterType(); value = (type != Object.class && !type.isArray() ? this.conversionService.convert(value, new TypeDescriptor(parameter), STRING_TARGET_TYPE) : this.conversionService.convert(value, String.class)); + if (!StringUtils.hasText((String) value) && !required && beforeValue == null) { + value = null; + } } if (value == null) { diff --git a/spring-web/src/test/java/org/springframework/web/service/invoker/NamedValueArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/service/invoker/NamedValueArgumentResolverTests.java index cbac555179ab..4e677140b52f 100644 --- a/spring-web/src/test/java/org/springframework/web/service/invoker/NamedValueArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/service/invoker/NamedValueArgumentResolverTests.java @@ -74,6 +74,12 @@ void dateTestValue() { assertTestValue("value", "2022-09-16"); } + @Test // gh-33794 + void dateNullValue() { + this.service.executeDate(null); + assertTestValue("value"); + } + @Test void objectTestValue() { this.service.execute(Boolean.TRUE); @@ -182,7 +188,7 @@ private interface Service { void executeString(@TestValue String value); @GetExchange - void executeDate(@TestValue @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate value); + void executeDate(@Nullable @TestValue(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate value); @GetExchange void execute(@TestValue Object value);