Creando restricciones personalizadas en Spring Boot (REST Api)
Tags: Spring Boot, Kotlin, Java, Programming

Si quieres validar tu objeto automáticamente en Spring Boot se puede usar “javax.validation.ConstraintValidator”. En esté post dejaré un ejemplo de cómo se puede crear uno especifico para tu projecto. En este ejemplo verificará si el campo LocalDate es mayor de edad.

También puedes usar los ya creados que puedes mirar aquí https://javaee.github.io/javaee-spec/javadocs/javax/validation/constraints/package-summary.html

Java

FullAge.java

import javax.validation.Constraint;

import javax.validation.Payload;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;

import java.lang.annotation.Target;



import static java.lang.annotation.ElementType.FIELD;

import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.RetentionPolicy.RUNTIME;



@Target({METHOD, FIELD})

@Retention(RUNTIME)

@Constraint(validatedBy = FullAgeValidator.class)

@Documented

public @interface FullAge {



String message() default "{com.ricardorb.config.constraints.FullAge}";



Class<?>[] groups() default {};



Class<? extends Payload>[] payload() default {};



int value();



}

FullAgeValidator.java

import javax.validation.ConstraintValidator;

import javax.validation.ConstraintValidatorContext;



public class FullAgeValidator implements ConstraintValidator<FullAge, String> {



private int age;



public void initialize(FullAge constraintAnnotation) {

this.age = constraintAnnotation.value();

}



public boolean isValid(String object, ConstraintValidatorContext constraintContext) {

return age > 18;

}



}

Kotlin

FullAge.kt

import javax.validation.Constraint

import javax.validation.ConstraintValidator

import javax.validation.ConstraintValidatorContext

import javax.validation.Payload

import kotlin.reflect.KClass



/**

* Annotation for constraint older than 18 years old

*/

@Target(AnnotationTarget.FIELD, AnnotationTarget.CONSTRUCTOR)

@Retention(AnnotationRetention.RUNTIME)

@Constraint(validatedBy = [FullAgeValidator::class])

annotation class FullAge(val message: String = "{com.getfoodin.foodinbe.config.constraints.FullAge}",

val groups: Array<KClass<*>> = [],

val payload: Array<KClass<out Payload>> = [])



/**

* ConstraintValidator that check whether a LocalDate is older than 18 years

*/

class FullAgeValidator : ConstraintValidator<FullAge, Int> {

override fun isValid(value: Int, context: ConstraintValidatorContext?): Boolean {

return value >= 18

}



}

Después de crearla, lo único que tenemos que hacer es añadir la anotación a nuestro pojo.

UserRequest.java

import com.ricardorb.config.constraints.FullAge;

import javax.validation.constraints.Email;

import javax.validation.constraints.NotBlank;



public class UserRequest {

@NotBlank

@Email

private String email;

private String name;

@FullAge

private Integer age;

}

UserRequest.kt

import com.ricardorb.config.constraints.FullAge;

import javax.validation.constraints.Email;

import javax.validation.constraints.NotBlank; data class UserRequest(

@field:NotBlank

@field:Email

val email: String,

val name: String? = "",

@field:FullAge

val age: Int

)

Por último, recordad que si no añadis la anotación @Validated a vuestro servicio y @Valid al parametro que queramos validar, spring no va a validar nuestra clase.

UserService.java

import org.springframework.stereotype.Service;

import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;



@Service

@Validated

public class UserService {



public UserResponse createUser(@Valid UserRequest userRequest) {

// Entrará siempre y cuándo sea valido nuestro parametro "userRequest"

return UserResponse()

}

}

UserService.kt