Home > Back-end >  Kotlin Spring Boot Webflux validate @RequestBody with @Valid annotation
Kotlin Spring Boot Webflux validate @RequestBody with @Valid annotation

Time:11-23

I have a simple REST API in Spring Boot with Webflux. I want to use a simple annotation based validation for the request body in my POST request.

RecipeModel.kt

package com.example.reactive.models

import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import org.springframework.stereotype.Component
import javax.validation.constraints.Max
import javax.validation.constraints.NotBlank

@Table("recipes")
data class Recipe (
    @Id
    val id: Long?,
    @NotBlank(message = "Title is required") 
    val title: String,
    @Max(10, message = "Description is too long") 
    val description: String?,
)

RecipeRepo.kt

package com.example.reactive.repositories

import com.example.reactive.models.Recipe
import org.springframework.data.repository.reactive.ReactiveCrudRepository
import org.springframework.stereotype.Repository

@Repository
interface RecipeRepo : ReactiveCrudRepository<Recipe, Long>

RecipeController.kt

package com.example.reactive.controllers

import com.example.reactive.models.Recipe
import com.example.reactive.models.RecipeMapper
import com.example.reactive.repositories.RecipeRepo
import com.example.reactive.services.RecipeService
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import javax.validation.Valid

@RestController
@RequestMapping("/recipes")
class RecipeController(val recipeService : RecipeService) {

 
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    fun createRecipe(@RequestBody payload: @Valid Recipe): Mono<Recipe> =
        recipeService.createRecipe(payload)


}

RecipeService.kt

package com.example.reactive.services

import com.example.reactive.models.Recipe
import com.example.reactive.models.RecipeMapper
import com.example.reactive.repositories.RecipeRepo
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

@Service
class RecipeService(val recipeRepo: RecipeRepo, val recipeMapper: RecipeMapper) {


    fun createRecipe(recipe: Recipe): Mono<Recipe> = recipeRepo.save(recipe)

}

EXPECTATION: When I provide a POST request with an empty string as title and/or a description with more than 10 characters I should not get a 201 CREATED as response.

Checking with Postman

As you can see I get a 201 CREATED as response.

Does anyone see where I made a mistake???

CodePudding user response:

You need a couple of changes in your Controller (@Valid placement):

@RestController
@RequestMapping("/recipes")
class RecipeController(val recipeService : RecipeService) {
 
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    fun createRecipe(@RequestBody @Valid payload: Recipe): Mono<Recipe> =
        recipeService.createRecipe(payload)
}

And also in the Model itself (you need to use @field:):

@Table("recipes")
data class Recipe (
    @field:Id
    val id: Long?,
    @field:NotBlank(message = "Title is required") 
    val title: String,
    @field:Max(10, message = "Description is too long") 
    val description: String?,
)
  • Related