Hoy vamos a hablar de las Type Annotations y como hacer las nuestras propias validaciones de codiga a traves de ellas.
Basicamente las Type Annotations es la posibilidad a partir de Java 8 de utilizarlas cada vez que indiquemos un tipo de clase. Es decir en: operadores new, cast de objetos, clausulas de implementacion o lanzamiento de excepciones, etc. Y esto es posible gracias al enumerado TYPE_USE, indicadolo en el apartado target.
@Target({ ElementType.TYPE_USE }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = { DNIValidator.class }) public @interface DNI { Class<?>[] groups() default {}; String message() default "DNI must be valid"; Class<? extends Payload>[] payload() default {}; }
Y para ver un ejemplo practico, anadiremos a esta informacion la de las ConstraintValidator (basadas en la especificacion JSR-380, tambien conociada como Bean Validation 2.0). La cual nos permitira validar el contenido de nuestros objetos en tiempo de ejecucion.
Para llevar a cabo el ejemplo necesitaremos las librerias
- hibernate-validator: Que contiene la implementacion de JSR-380.
- hibernate-validator-annotation-processor: Que permite el procesamiento de las anotaciones.
- javax.el: Que habilita el uso de EL para el manejo de mensajes en las anotaciones.
El ejemplo lo basaremos en la anotacion mostrada anteriormente pero para ello antes hay que explicar el resto del codigo que es obligatorio para el correcto funcionamiento.
- Anotacion Retention: Donde le indicaremos la permanencia de la anotacion. Puede ser @Source que descarta la anotacion durante la compilacion, @Class descarta la anotacion durante la carga de la clase y @Runtime que mantiene siempre la anotacion.
- Anotacion Constraint: Aqui indicaremos la clase o clases de validacion que queremos asociarle.
- Atributo groups: Donde le indicamos la agrupacion jerarquica de la anotacion, permitiendo a la hora de indicar la anotacion, a que grupos se aplica.
- Atributo message: Donde indicamos el mensaje de validacion asociado.
- Atributo payload: A traves del cual indicamos metadatos asociados a la naotacion.
import java.util.regex.*; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext;
public class DNIValidator implements ConstraintValidator<DNI, String> { private static String REGEX = "\\d{8}[A-HJ-NP-TV-Z]"; @Override public boolean isValid(final String arg0, final ConstraintValidatorContext arg1) { Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(arg0); return m.matches(); } }
Ahora solo nos quedaria la prueba. Para ellos crearemos una clase denominada group que contenga un grupo de personas (un mapa) donde indicaremos la anotacion tipada @DNI. Y posteriormente probaremos la clase y su validacion a traves de JUnit y ValidatorFactory.
public class Group { private Map<@DNI String, String> people = new HashMap<>(); public void addPeople(final String dni, final String name) { people.put(dni, name); } } // ... public class DNIValidatorTest { private Validator validator; @Test public void ko() { Group group = new Group(); group.addPeople("01234567U", "Daniel"); Set<ConstraintViolation<Group>> violations = validator.validate(group); assertThat(violations.isEmpty(), is(false)); } @BeforeEach public void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } }
No hay comentarios:
Publicar un comentario