Spring webflux bean validation not working

后端 未结 3 1586
南笙
南笙 2021-02-15 17:56

I am trying to use bean validation in Webflux. This is what I have so far:

@PostMapping(\"contact\")
fun create(@RequestBody @Valid contact: Mono)         


        
相关标签:
3条回答
  • 2021-02-15 18:26

    You need to also add bindingResult: BindingResult to as an extra parameter. When the method begins you can do something like bindingResult.isValid(). We use an aspect over all controller methods to return an error message with the validation errors to the user.

    0 讨论(0)
  • 2021-02-15 18:40

    I had to combine few of the answers from SO to get the validation correct. What I did was:

    • Made my data class as suggested here.

      • Then i used javax.validation.Validator class to validate the data class.

    import javax.validation.Validator import javax.validation.ConstraintViolationException

    @Service
    open class MyService {
        @Autowired
        lateinit var repository: UserRepository
    
        @Autowired
        lateinit var validator: Validator
    
         open fun createUser(user: User): Mono<User> {
             val violations = validator.validate(user)
              //if it violates our constraints, it will throw an exception, which we 
              //handle using global exception handler
              if(violations.isNotEmpty()){
                   throw ConstraintViolationException(violations)
               }
               return repo.save(user)
             }
    . . .
    }
    
    • Add these lines in application.properties.
    spring.mvc.throw-exception-if-no-handler-found=true
    spring.resources.add-mappings=false
    

    And to catch the exceptions.

    @RestControllerAdvice    
    open class ExceptionHandlers {
    
      @ExceptionHandler(ConstraintViolationException::class)
      @ResponseStatus(HttpStatus.BAD_REQUEST)
      fun throwConstraintViolationExcetion(ex: ConstraintViolationException): ApiResponse {
        return ApiResponse (message= ex.message.toString(), data= null);
      }
    }
    

    p.s ApiResponse is just a data class that takes server message & data as parameters. No need to handle errors in @Controller as it will be thrown by the @Service class

    0 讨论(0)
  • 2021-02-15 18:43

    The annotations you have placed in the example project are actually annotations on the constructor parameters of the Ticket class. For Spring validation, you need to annotate the fields instead. You can do this in Kotlin by using annotation use-site targets.

    In this specific case, your Ticket class should look like this:

    data class Ticket(
            @field:Id
            @field:JsonSerialize(using = ToStringSerializer::class)
            val id: ObjectId = ObjectId.get(),
    
            @field:Email
            @field:Max(200)
            @field:NotEmpty
            val email: String,
    
            @field:NotEmpty
            @field:Size(min = 2, max = 200)
            val name: String,
    
            @field:NotEmpty
            @field:Size(min = 10, max = 2000)
            val message: String
    )
    

    This, along with the following controller function will work and return errors as expected:

    @PostMapping("tickets")
    fun create(@RequestBody @Valid contact: Mono<Ticket>) : Mono<Ticket> {
        return contact.flatMap { ticketRepository.save(it) }
                .doOnError{ Error("test") }
    }
    
    0 讨论(0)
提交回复
热议问题