From 39e38763019a2b919988b3d6e8eefb266a7f75c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Bouz=C3=B3n=20Garc=C3=ADa?= Date: Fri, 6 May 2022 00:00:02 +0200 Subject: [PATCH 1/2] Fix BindingResult error when ModelAttribute has custom name in WebFlux Closes gh-28422 --- .../ErrorsMethodArgumentResolver.java | 2 +- .../ErrorsMethodArgumentResolverTests.java | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) 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 28abd49dfd..4493f0416d 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 @@ public class ErrorsMethodArgumentResolver extends HandlerMethodArgumentResolverS "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 38467b7107..44e0c70800 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 @@ class ErrorsMethodArgumentResolverTests { 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 @@ class ErrorsMethodArgumentResolverTests { 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 @@ class ErrorsMethodArgumentResolverTests { String string) { } + @SuppressWarnings("unused") + void handleWithModelAttributeValue( + @ModelAttribute("custom") Foo foo, + Errors errors, + @ModelAttribute Mono fooMono, + BindingResult bindingResult, + Mono errorsMono, + String string) { + } } From 64c96c579df7a2a9153732881632f9f4bfb856b7 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sat, 7 May 2022 16:14:41 +0200 Subject: [PATCH 2/2] Polish contribution See gh-28422 --- .../annotation/ErrorsMethodArgumentResolver.java | 5 +++-- .../ErrorsMethodArgumentResolverTests.java | 15 +++++++-------- 2 files changed, 10 insertions(+), 10 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 4493f0416d..7f6a1dea9f 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,8 @@ import org.springframework.web.server.ServerWebExchange; /** * Resolve {@link Errors} or {@link BindingResult} method arguments. - * An {@code Errors} argument is expected to appear immediately after the + * + *

An {@code Errors} argument is expected to appear immediately after the * model attribute in the method signature. * * @author Rossen Stoyanchev 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 44e0c70800..499a5b85da 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,12 +82,11 @@ class ErrorsMethodArgumentResolverTests { } @Test - void resolveOnBindingResultAndModelAttributeWithCustomValue() { + void resolveOnBindingResultAndModelAttributeWithCustomName() { 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(); + ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handleWithCustomModelAttributeName").build(); MethodParameter parameter = testMethod.arg(Errors.class); Object actual = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange) @@ -114,12 +113,11 @@ class ErrorsMethodArgumentResolverTests { } @Test - void resolveWithMonoOnBindingResultAndModelAttributeWithCustomValue() { + void resolveWithMonoOnBindingResultAndModelAttributeWithCustomName() { 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(); + ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handleWithCustomModelAttributeName").build(); MethodParameter parameter = testMethod.arg(Errors.class); Object actual = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange) @@ -181,7 +179,7 @@ class ErrorsMethodArgumentResolverTests { } @SuppressWarnings("unused") - void handleWithModelAttributeValue( + void handleWithCustomModelAttributeName( @ModelAttribute("custom") Foo foo, Errors errors, @ModelAttribute Mono fooMono, @@ -189,4 +187,5 @@ class ErrorsMethodArgumentResolverTests { Mono errorsMono, String string) { } + }