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 28abd49dfd93..4493f0416d9c 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 @@ -86,7 +86,7 @@ private Object getErrors(MethodParameter parameter, BindingContext context) { "Either declare the @ModelAttribute without an async wrapper type or " + "handle a WebExchangeBindException error signal through the async type."); - ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class); + ModelAttribute ann = attributeParam.getParameterAnnotation(ModelAttribute.class); String name = (ann != null && StringUtils.hasText(ann.value()) ? ann.value() : Conventions.getVariableNameForParameter(attributeParam)); Object errors = context.getModel().asMap().get(BindingResult.MODEL_KEY_PREFIX + name); 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 38467b710782..44e0c7080078 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 @@ -81,6 +81,21 @@ void resolve() { assertThat(actual).isSameAs(bindingResult); } + @Test + void resolveOnBindingResultAndModelAttributeWithCustomValue() { + BindingResult bindingResult = createBindingResult(new Foo(), "custom"); + this.bindingContext.getModel().asMap().put(BindingResult.MODEL_KEY_PREFIX + "custom", bindingResult); + + ResolvableMethod testMethod = ResolvableMethod.on(getClass()) + .named("handleWithModelAttributeValue").build(); + + MethodParameter parameter = testMethod.arg(Errors.class); + Object actual = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange) + .block(Duration.ofMillis(5000)); + + assertThat(actual).isSameAs(bindingResult); + } + private BindingResult createBindingResult(Foo target, String name) { DataBinder binder = this.bindingContext.createDataBinder(this.exchange, target, name); return binder.getBindingResult(); @@ -98,6 +113,21 @@ void resolveWithMono() { assertThat(actual).isSameAs(bindingResult); } + @Test + void resolveWithMonoOnBindingResultAndModelAttributeWithCustomValue() { + BindingResult bindingResult = createBindingResult(new Foo(), "custom"); + this.bindingContext.getModel().asMap().put(BindingResult.MODEL_KEY_PREFIX + "custom", Mono.just(bindingResult)); + + ResolvableMethod testMethod = ResolvableMethod.on(getClass()) + .named("handleWithModelAttributeValue").build(); + + MethodParameter parameter = testMethod.arg(Errors.class); + Object actual = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange) + .block(Duration.ofMillis(5000)); + + assertThat(actual).isSameAs(bindingResult); + } + @Test void resolveWithMonoOnBindingResultAndModelAttribute() { MethodParameter parameter = this.testMethod.arg(BindingResult.class); @@ -150,4 +180,13 @@ void handle( String string) { } + @SuppressWarnings("unused") + void handleWithModelAttributeValue( + @ModelAttribute("custom") Foo foo, + Errors errors, + @ModelAttribute Mono fooMono, + BindingResult bindingResult, + Mono errorsMono, + String string) { + } }