From 7dd622bdb28436f859b05956b78ed573fb5bd881 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sat, 7 May 2022 17:14:59 +0200 Subject: [PATCH] Support name attribute in @ModelAttribute in WebFlux Prior to this commit, the `name` attribute in @ModelAttribute was not supported when using WebFlux. This is because MethodParameter was used instead of SynthesizingMethodParameter when retrieving the @ModelAttribute annotation. In other words, @AliasFor was not honored because the annotation was not synthesized. Consequently, only the `value` attribute was supported in WebFlux when specifying a custom name via @ModelAttribute. This commit fixes this by using SynthesizingMethodParameter to retrieve the @ModelAttribute annotation. Closes gh-28423 --- .../method/annotation/ErrorsMethodArgumentResolver.java | 8 +++++--- .../annotation/ErrorsMethodArgumentResolverTests.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolver.java index 7f6a1dea9f5a..ad66fc802819 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolver.java @@ -22,6 +22,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; @@ -38,6 +39,7 @@ * model attribute in the method signature. * * @author Rossen Stoyanchev + * @author Sam Brannen * @since 5.0 */ public class ErrorsMethodArgumentResolver extends HandlerMethodArgumentResolverSupport { @@ -79,7 +81,7 @@ private Object getErrors(MethodParameter parameter, BindingContext context) { "Errors argument must be declared immediately after a model attribute argument"); int index = parameter.getParameterIndex() - 1; - MethodParameter attributeParam = MethodParameter.forExecutable(parameter.getExecutable(), index); + MethodParameter attributeParam = SynthesizingMethodParameter.forExecutable(parameter.getExecutable(), index); ReactiveAdapter adapter = getAdapterRegistry().getAdapter(attributeParam.getParameterType()); Assert.state(adapter == null, "An @ModelAttribute and an Errors/BindingResult argument " + @@ -88,8 +90,8 @@ private Object getErrors(MethodParameter parameter, BindingContext context) { "handle a WebExchangeBindException error signal through the async type."); ModelAttribute ann = attributeParam.getParameterAnnotation(ModelAttribute.class); - String name = (ann != null && StringUtils.hasText(ann.value()) ? - ann.value() : Conventions.getVariableNameForParameter(attributeParam)); + String name = (ann != null && StringUtils.hasText(ann.name()) ? ann.name() : + Conventions.getVariableNameForParameter(attributeParam)); Object errors = context.getModel().asMap().get(BindingResult.MODEL_KEY_PREFIX + name); Assert.state(errors != null, () -> "An Errors/BindingResult argument is expected " + diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolverTests.java index 499a5b85dab6..504122477ef1 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/ErrorsMethodArgumentResolverTests.java @@ -180,7 +180,7 @@ void handle( @SuppressWarnings("unused") void handleWithCustomModelAttributeName( - @ModelAttribute("custom") Foo foo, + @ModelAttribute(name = "custom") Foo foo, Errors errors, @ModelAttribute Mono fooMono, BindingResult bindingResult,