How to validate Mono when using Spring Reactive

南楼画角 提交于 2019-12-08 03:25:45

问题


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 Monos and Fluxes, and then sending a suitable error response?


回答1:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!