Validation no Spring Boot com Kotlin + Custom Validation (@EmailAvailable)
A validação no Spring Boot permite validar campos de DTOs usando anotações como:
- @NotEmpty
- @NotBlank
- @Size
- @Min
- @Max
Para instalar as dependências coloque esse implementation no seu gradle:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-validation")
}Com uma simples anotação em nossos Dtos:
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotEmpty
data class PostCustomerRequest(
@field:NotEmpty(message = "Nome não por ser vazio")
var name:String,
@field:Email(message = "Email inválido")
var email:String
)Ativando a validação no Controller, nota a anotação @Valid:
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(
@RequestBody @Valid request: PostCustomerRequest
) {
customerService.create(request)
}Quando alguma regra falhar, o Spring lançará:
MethodArgumentNotValidExceptionPara tratar esse erro usamos um ControllerAdivace, se você ainda não viu como funciona o controller adivace acesse aqui. Vamos ao código do metódo:
@ExceptionHandler(MethodArgumentNotValidException::class)
fun handleMethodArgumentNotValidException(ex:MethodArgumentNotValidException,request:WebRequest):ResponseEntity<ErrorResponse>{
val erro = ErrorResponse(
httpCode = HttpStatus.UNPROCESSABLE_ENTITY.value(),
message = Errors.ML001.message,
internalCode = Errors.ML001.code,
erros = ex.bindingResult.fieldErrors.map {
FieldErrorResponse(it.defaultMessage?:"invalid",it.field)
}
)
return ResponseEntity(erro, HttpStatus.UNPROCESSABLE_ENTITY)
}Além disso, podemos criar validações personalizadas, como verificar se um e-mail já existe no banco de dados. Vamos ver como fazer isso, primeiro vamos criar a classe EmailAvailable:
import jakarta.validation.Constraint
import jakarta.validation.Payload
import kotlin.reflect.KClass
@Constraint(validatedBy = [EmailAvailableValidator::class])
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class EmailAvailable(
val message: String = "Email já cadastrado",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<out Payload>> = []
)Depois criamos a classe EmailAvailableValidator. Em ConstraintValidator<Nossa anotação,Tipo do atributo que vamos verificar>. Também chamamos o service para ter acesso ao banco de dados e antes de inserir algum dado, ele fala se o email já existe no banco de dados.
import jakarta.validation.ConstraintValidator
import jakarta.validation.ConstraintValidatorContext
import mercado_livro.service.CustomerService
class EmailAvailableValidator(
var customerService: CustomerService
):ConstraintValidator<EmailAvailable,String> {
override fun isValid(value: String?, p1: ConstraintValidatorContext?): Boolean {
if(value.isNullOrEmpty()){
return false
}
return customerService.emailAvailable(value)
}
}Agora é só usar a nossa anotação:
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotEmpty
import mercado_livro.validation.EmailAvailable
data class PostCustomerRequest(
@field:NotEmpty(message = "Nome não por ser vazio")
var name:String,
@field:Email(message = "Email inválido")
@EmailAvailable
var email:String
)
0 comentários