Otro problema que necesitamos resolver, es que el mensaje de error a emitir, puede ser distinto según el error que exista; en este caso vamos a ver como tratar dos mensajes de error en el mismo campo de fecha; uno cuando el formato de entrada es erróneo, y otro cuando la fecha sea anterior a la actual, y, todo eso, creando una anotación (CheckFechaFuturaValidation)
Preparando el entorno
Para poder crear y utilizar las anotaciones en un programa de SpringBoot, debemos añadir una dependencia, si estas utilizando Maven, deberás añadir
<!-- Para las validaciones -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- fin validaciones -->
Creando la anotación @CheckFechaFuturaValidation
Como ya vimos anterioermente (aqui para @DniConstraint, y aqui para @CheckCineValidation), lo primero es crear la interface que nos define el nombre, por lo que, escribimos
CheckFechaFuturaValidation.java
package com.recursosformacion.lcs.util.constraint.interfaces;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.recursosformacion.lcs.util.constraint.validator.CheckFechaFuturaValidator;
import java.lang.annotation.RetentionPolicy;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import jakarta.validation.Payload;
import jakarta.validation.Constraint;
@Target( { FIELD, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = CheckFechaFuturaValidator.class)
public @interface CheckFechaFuturaValidation {
public String message() default "La fecha es en formato dd/mm/yyyy y ha de ser actual o futura";
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default {};
}
Aunque luego, utilizaremos mensajes mejor orientados, aqui dejo definido un posible mensaje, mas que nada, para documentación. El resto de datos son los que he ido comentando en articulos precedentes.
El siguiente paso, es crear la clase que utilizaremos para validar.
Esta clase, debe implementar otra Interfaz, (ConstraintValidator) que es generica, y debemos incluir el nombre de la Interfaz generada anteriormente, y el tipo de campo que vamos a recibir, a continuacion, os indico mi clase
CheckFechaFuturaValidator.java
package com.recursosformacion.lcs.util.constraint.validator;
import java.time.LocalDate;
import com.recursosformacion.lcs.util.Rutinas;
import com.recursosformacion.lcs.util.constraint.interfaces.CheckFechaFuturaValidation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class CheckFechaFuturaValidator implements ConstraintValidator<CheckFechaFuturaValidation, String> {
final String FECHA_FORMATO_ERRONEO = "La fecha debe tener un formato dd/mm/aaaa";
final String FECHA_INTERVALO = "La fecha ha de ser actual o futura (Nunca en el pasado)";
@Override
public boolean isValid(String fecha, ConstraintValidatorContext ctx) {
if (null == fecha) {
return true;
}
ctx.disableDefaultConstraintViolation();
if (!Rutinas.esFechaValida(fecha)) {
ctx.buildConstraintViolationWithTemplate( FECHA_FORMATO_ERRONEO).addConstraintViolation();
return false;
}
if (!Rutinas.isGreaterOrEqual(Rutinas.fechaToLocalDate(fecha), LocalDate.now())) {
ctx.buildConstraintViolationWithTemplate( FECHA_INTERVALO).addConstraintViolation();
return false;
}
return true;
}
}
Como siempre, he utilizado el módulo Rutinas, que ya habíamos visto y testeado al inicio de la serie, pero esta vez, para poder cambiar los mensajes, debo deshabilitar el mensaje por defecto (ctx.disableDefaultConstraintViolation()😉 y luego añado el mensaje que me interesa , una vez detectado el error concreto. Como podeis ver, no es demasiado complicado
Ya despues, solo queda añadir la validación al campo indicado, que en mi caso es en EntradaDTO
Naturalmente, este campo debe recibir una String, si no, no tendría sentido comprobar formato, pero como este DTO es para la entrada, se adapta perfectamente
Como siempre, nos aseguramos que el controlador tenga especificado el @Valid alli donde queramos comprobar los datos; en mi caso, en el Post
y en el Update
y lanzamos la prueba con Postman, teniendo activo nuestro ControllerExceptionValidation que veremos en el siguiente articulo
En caso de que indiquemos mal el intervalo, si nos equivocaramos en el formato, seria
Y, si no indicáramos fecha, seria:
Conclusión
Todo este desarrollo lo teneis explicado con mas detalle en youTube (a partir de1/02/24) , y, aunque es conveniente que intentéis escribirlo TODO vosotros, si queréis renunciar a ello, lo teneis tambien en GitHub
Este desarrollo esta hecho para disponer de un fuente para explicar otros temas, tal y como se indica en Visión de conjunto con Spring
Relacionado
Descubre más desde Recursos para formacion
Suscríbete y recibe las últimas entradas en tu correo electrónico.