Poco a poco, nos hemos ido acostumbrando a las anotaciones de Hibernate, para filtrar el contenido de los campos (@NotNull,@Size, …), pero, realmente, el numero de comprobaciones es muy corto, y nosotros repetimos mucho los filtros…lo ideal, seria poder crear anotaciones que realizaran esa funcion, y que las pudiéramos programar… y eso es bastante fácil de hacer en el entorno de SpringBoot que estamos utilizando.
Realmente, es una opción de JPA, pero… es lo mismo ¿no?
Leer más: Creacion de anotaciones para filtrosPreparando 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 @DniConstraint
Para crear cualquier anotacion, deberemos definir una interface, y luego una clase; como puedes imaginar, los nombres pueden ser cualquiera, yo me he limitado a utilizar aquellos nombres que tuvieran sentido para mi, y con eso, y en un nuevo package, creo la interface
DniConstraint.java
package com.recursosformacion.lcs.util.constraint.interfaces;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import com.recursosformacion.lcs.util.constraint.validator.DniConstraintValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
@Documented
@Constraint(validatedBy = DniConstraintValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DniConstraint {
String message() default "DNI - valor falso";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
De esta interface necesitamos saber:
- @Constraint – Indicaremos el nombre de la clase que vamos a escribir para realizar la validación
- @Target – Para señalar que la validación (realmente, la anotación) se realiza a nivel de campo
- String message() default «DNI – valor falso»; – para indicar el tipo de mensaje que queremos emitir (por defecto), cuando el dato sea erroneo
Solo recordaros que con versiones superior a 11, debemos utilizar jakarta……..
El siguiente paso, es crear la clase que utilizaremos para validar.
Esta clase, debe implementar otra Interfaz, (ConstraintValidator) que es genérica, y debemos incluir el nombre de la Interfaz generada anteriormente, y el tipo de campo que vamos a recibir, a continuación, os indico mi clase
DniConstraintValidator.java
package com.recursosformacion.lcs.util.constraint.validator;
import com.recursosformacion.lcs.util.Rutinas;
import com.recursosformacion.lcs.util.constraint.interfaces.DniConstraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class DniConstraintValidator implements ConstraintValidator<DniConstraint, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && Rutinas.cumpleDNI(value);
}
}
En este caso, yo tengo una clase estática que contiene todas las depuraciones, pero si no trabajas asi, solo tiene que implementar la rutina isValid que devuelve true o false, según lo que llegue en value sea valido o no
Para utilizar la anotación. podeis hacer algo como
Al campo idCliente, le he añadido mas validaciones, para conseguir mas detalle, ya que en la rutina no lo filtro de forma separada,,,,
Por ultimo, el controlador debe exigir que se valide
Si la validación falla, lanza una excepción de tipo MethodArgumentNotValidException
A continuación, os presento la respuesta que daría en caso de error.
Esta es la salida utilizando un modulo de tratamiento de errores
Ese modulo, lo comentare en el siguiente Post, mientras tanto, la salida de error seria algo como
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