Creación de validadores en Spring Boot

validadores en spring boot

validadores-spring-boot


Spring Boot nos ofrece muchas facilidades en modo de anotaciones para crear nuestras aplicaciones, algunas de esas anotaciones son validadores para tener un mayor control de errores y restricciones en nuestros servicios. En esta entrada vamos a ver la creación de validadores en Spring Boot para poder crear anotaciones propias para añadir restricciones a nuestras clases.

Crear validadores custom en Spring Boot nos va a facilitar eliminar código verboso y boilerplate de nuestras aplicaciones y nos simplifica su construcción. Es por ese motivo que en esta entrada vamos a ver un ejemplo para la creación y construcción de un validador en Spring Boot.

Dependencias para crear un validador en Spring Boot

Para crear una anotación propia en Spring Boot para la creación de un validador, lo primero que tenemos que hacer es añadir la siguiente dependencia de Spring Boot en nuestro pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Esta dependencia añadirá las librerías necesarias (validador de Hibernate JSR 380) que permitirá las restricciones y validaciones que necesitamos.

Crear anotación para un Validador en Spring Boot

A continuación vamos a crear una anotación en Java para validar a nivel de campo que la longitud de un String no es mayor de 10. Como ya vimos en un artículo anterior, las anotaciones se pueden crear a nivel de campo, constructor, método etc…

La anotación que vamos a realizar será a nivel de campo por lo que el target llevará field:

@Target( { FIELD, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = LengthValidator.class)
public @interface LengthValidation {
    public String message() default "Invalid length: the length must be less than 10";
    public Class<?>[] groups() default {};
    public Class<? extends Payload>[] payload() default {};
}

La clase que se encargará de añadir la lógica necesaria será lengthValidator. Como podemos ver el mensaje de error será propagado por la clase de la interfaz en el campo message.

Crear lógica en un Validador Custom en Spring Boot

A continuación vamos a hacer uso de ConstraintValidator para crear nuestro propio validador en Spring Boot y sacar el mensaje de error que hemos creado anteriormente cuando la longitud de un campo sea igual o superior a 10.

public class LengthValidator implements ConstraintValidator<LengthValidation, String>
{
    public boolean isValid(String field, ConstraintValidatorContext cxt) {
        return field.length < 10;
    }
}

Al hacer uso de ConstratintValidator tenemos que implementar el método isValid, el cual devolverá False o True en función de la condición de salida.

Uso del Validador custom creado en Spring Boot

Para añadir la validación vamos a partir un ejemplo anterior sobre validadores de un ejemplo anterior que tenemos en nuestro github al cual vamos a añadir nuestro validador custom.

Una vez hemos creado el validador lo ideal es añadirlo como anotación en el campo de la clase que queremos cumplir esa restrición. Por ejemplo, vamos a añadirlo al siguiente campo:

@Entity
@NoArgsConstructor
@Getter
@Setter
public class CarEntity {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @NotNull
  @NotBlank
  private String color;

  @NotNull
  private String model;

  @NotNull
  @NotBlank(message = "plate is required")
  @Size(min = 5, max = 10)
  private String plate;

  @LengthValidation
  private String origin

}

Y lo mismo vamos a hacer con el DTO para validar la entrada a nuestro controlador:

@Getter
@Setter
@NoArgsConstructor
public class CarDTO {
  @NotNull
  @NotBlank
  private String color;

  @NotNull
  private String model;

  @NotNull
  @NotBlank(message = "plate is required")
  @Size(min = 5, max = 10)
  private String plate;

  @LengthValidation
  private String origin
}

Una vez hemos añadido el validador a nuestro campo es el momento de crear un controlador que será el punto de entrada a nuestra aplicación. Vamos a reutilizar el controlador del ejemplo que hemos comentado de un artículo anterior

Creción del controlador

A continuación creamos un controlador que será el punto de entrada a nuestra aplicación:

@RequiredArgsConstructor
@RequestMapping("/cars")
@RestController
public class CarController {

  private final CarRepository carRepository;

  private final CarMapper carMapper;

  @PostMapping
  public ResponseEntity<CarDTO> saveCar(@Valid @RequestBody CarDTO carDTO) {

    var car = carMapper.toDto(
        carRepository.save(carMapper.toEntity(carDTO)));

    return ResponseEntity.ok(car);

  }
}

y una vez hemos realizado nuestro controlador necesitamos verificar que nuestro código esta bien, obviamente haremos alguna prueba de manera manual, con curl o haciendo uso de postman. Pero sin duda la mejor manera de estar seguro que nuestro código es correcto es realizando tests, y para esto Spring Boot nos proporciona muchas herramientas.

Creación de tests para un Validador Custom

Vamos a validar que nuestro código funciona correctamente para ello vamos a crear un test integrado y un test unitario.

Los siguientes test unitarios validan nuestro validador:

    @Test
    void whenValidatorIsInvoked_givenAStringGreaterThan10_thenReturnFalse() throws Exception {

        LengthValidator lengthValidator = new LengthValidator();
        Boolean isValid = lengthValidator.isValid("dfaiuruqrqurewqrewqfdsa", null);

        assert !isValid;

    }

    @Test
    void whenValidatorIsInvoked_givenAStringLessThan10_thenReturnTrue() throws Exception {

        LengthValidator lengthValidator = new LengthValidator();
        Boolean isValid = lengthValidator.isValid("df", null);

        assert isValid;

    }

Y el siguiente es un test integrado en el que nuestro código lanzará un 4XX si la longitud del campo origin es superior a 10:

  @Test
  void whenSaveCarIsInvoked_givenALengthGreaterThan10_thenErrorIsReturned() throws Exception {

    CarDTO carDTO = createCarDTO();
    carDTO.setPlate("ASDFGA");
    carDTO.setOrigin("ASDFGPOIERTUYUWE");
    mockMvc.perform(
                    MockMvcRequestBuilders.post("/cars")
                            .contentType(MediaType.APPLICATION_JSON)
                            .content(asJsonString(carDTO)))
            .andExpect(status().is4xxClientError());

  }

Una vez hemos terminado los test, lo mejor sería añadir un @controllerAdvice para la gestión de errores y así mostrar los errores con un body concreto.

Conclusión

En esta entrada hemos podido ver la creación de validadores en Spring Boot para poder simplificar nuestro código a través de anotaciones y añadir restricciones.

Si quieres echar un vistazo al ejemplo completo lo puedes hacer aquí.

Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!


Deja una respuesta

Tu dirección de correo electrónico no será publicada.