We are evaluating Spring 5 for a project, and not sure how best to validate Mono
parameters. Traditionally we had been using MethodValidationPostProcessor to validate our method parameters as below:
@Validated
@Service
public class FooService
@Validated(SignUpValidation.class)
public void signup(@Valid UserCommand userCommand) {
...
}
We would then handle the exception in a ControllerAdvice
or ErrorController
, and pass a suitable 4xx response to the client.
But when I change the parameter to Mono
, as below, it no more seems to work.
@Validated
@Service
public class FooService
@Validated(SignUpValidation.class)
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand) {
...
}
As I understand Spring Reactive, probably it's actually not supposed to work. So, what would be Spring 5 best practices for validating Mono
s and Flux
es, and then sending a suitable error response?
Quick not before answering that question, the void
return type of your method is quite unusual in a reactive application. Looking at this, it seems this method should perform actual work asynchronously but the method returns a synchronous type. I've changed that as a Mono<Void>
in my answer.
As stated in the reference documentation, Spring WebFlux does support validation.
But best practices differ here, because method parameters can be reactive types. You can't have the validation result if the method parameter hasn't been resolved yet.
So something like that won't really work:
// can't have the BindingResult synchronously,
// as the userCommand hasn't been resolved yet
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand, BindingResult result)
// while technically feasible, you'd have to resolve
// the userCommand first and then look at the validation result
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand, Mono<BindingResult> result)
Something more idiomatic and easier to use with reactive operators:
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand) {
/*
* a WebExchangeBindException will flow through the pipeline
* in case of validation error.
* you can use onErrorResume or other onError* operators
* to map the given exception to a custom one
*/
return userCommand.onErrorResume(t -> Mono.error(...)).then();
}
来源:https://stackoverflow.com/questions/47244769/how-to-validate-mono-when-using-spring-reactive