Spring webflux bean validation not working

匆匆过客 提交于 2020-01-13 08:57:27

问题


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

@PostMapping("contact")
fun create(@RequestBody @Valid contact: Mono<Contact>) : Mono<Contact> {
    return contact.flatMap { contactRepository.save(it) }
            .doOnError{ Error("test") }
}

The The validation doesn't work... I would expect that the Error("test") would be shown...

Does someone has a working example(Java or Kotlin)?

UPDATE

Here is a repository so it can be reproducted: https://github.com/jwz104/webflux-validation-test

Request:

curl --request POST \
  --url http://localhost:8080/tickets \
  --header 'content-type: application/json' \
  --data '{
    "email": "",
    "name": "",
    "message": ""
}'

Renamed contact to ticket, but everything is still the same.


回答1:


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") }
}



回答2:


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




回答3:


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.



来源:https://stackoverflow.com/questions/48439953/spring-webflux-bean-validation-not-working

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