1. Información general
En este tutorial rápido, cubrimos los conceptos básicos de la validación de un bean Java con el marco estándar: JSR 380, también conocido como Bean Validation 2.0 .
Validar la entrada del usuario es un requisito muy común en la mayoría de las aplicaciones. Y el marco de Java Bean Validation se ha convertido en el estándar de facto para manejar este tipo de lógica.
2. JSR 380
JSR 380 es una especificación de la API de Java para la validación de beans, que forma parte de Jakarta EE y JavaSE. Esto asegura que las propiedades de un bean cumplen con criterios específicos, utilizando anotaciones como @NotNull , @Min y @Max .
Esta versión requiere Java 8 o superior y aprovecha las nuevas características agregadas en Java 8, como anotaciones de tipo y compatibilidad con nuevos tipos como Optional y LocalDate .
Para obtener información completa sobre las especificaciones, siga adelante y lea el JSR 380.
3. Dependencias
Usaremos un ejemplo de Maven para mostrar las dependencias requeridas. Pero, por supuesto, estos frascos se pueden agregar de varias maneras.
3.1. API de validación
Según la especificación JSR 380, la dependencia validation-api contiene las API de validación estándar:
javax.validation validation-api 2.0.1.Final
3.2. Implementación de referencia de la API de validación
Hibernate Validator es la implementación de referencia de la API de validación.
Para usarlo, necesitamos agregar la siguiente dependencia:
org.hibernate.validator hibernate-validator 6.0.13.Final
Una nota rápida: hibernate-validator está completamente separado de los aspectos de persistencia de Hibernate. Entonces, al agregarlo como una dependencia, no agregamos estos aspectos de persistencia al proyecto.
3.3. Dependencias del lenguaje de expresión
JSR 380 admite la interpolación de variables, lo que permite expresiones dentro de los mensajes de violación.
Para analizar estas expresiones, agregaremos la dependencia javax.el de GlassFish, que contiene una implementación de la especificación del lenguaje de expresión:
org.glassfish javax.el 3.0.0
4. Uso de anotaciones de validación
Aquí, tomaremos un bean de usuario y trabajaremos en agregarle una validación simple:
import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.validation.constraints.Email; public class User { @NotNull(message = "Name cannot be null") private String name; @AssertTrue private boolean working; @Size(min = 10, max = 200, message = "About Me must be between 10 and 200 characters") private String aboutMe; @Min(value = 18, message = "Age should not be less than 18") @Max(value = 150, message = "Age should not be greater than 150") private int age; @Email(message = "Email should be valid") private String email; // standard setters and getters }
Todas las anotaciones utilizadas en el ejemplo son anotaciones JSR estándar:
- @NotNull valida que el valor de la propiedad anotado no es nulo .
- @AssertTrue valida que el valor de la propiedad anotado sea verdadero.
- @Size valida que el valor de la propiedad anotado tiene un tamaño entre los atributos min y max ; se puede aplicar a laspropiedades de cadena , colección , mapa y matriz.
- @Min valida que la propiedad anotada tiene un valor no menor que elatributo value .
- @Max valida que la propiedad anotada tiene un valor no mayor que elatributo value .
- @Email valida que la propiedad anotada es una dirección de correo electrónico válida.
Algunas anotaciones aceptan atributos adicionales, pero el atributo de mensaje es común a todos ellos. Este es el mensaje que normalmente se presentará cuando el valor de la propiedad respectiva falle la validación.
Y algunas anotaciones adicionales que se pueden encontrar en JSR:
- @NotEmpty valida que la propiedad no sea nula ni esté vacía; se puede aplicar avalores de cadena , colección , mapa o matriz .
- @NotBlank solo se puede aplicar a valores de texto y valida que la propiedad no sea nula ni espacios en blanco.
- @Positive y @PositiveOrZero se aplican a valores numéricos y validan que sean estrictamente positivos o positivos, incluido 0.
- @Negative y @NegativeOrZero se aplican a valores numéricos y validan que sean estrictamente negativos o negativos, incluido 0.
- @Past y @PastOrPresent validan que un valor de fecha está en el pasado o en el pasado, incluido el presente; se puede aplicar a tipos de fecha, incluidos los agregados en Java 8.
- @Future y @FutureOrPresent validan que un valor de fecha está en el futuro, o en el futuro, incluido el presente.
Las anotaciones de validación también se pueden aplicar a elementos de una colección :
List preferences;
En este caso, se validará cualquier valor agregado a la lista de preferencias.
Además, la especificación admite el nuevo tipo Opcional en Java 8:
private LocalDate dateOfBirth; public Optional getDateOfBirth() { return Optional.of(dateOfBirth); }
Aquí, el marco de validación desenvolverá automáticamente el valor LocalDate y lo validará.
5. Validación programática
Algunos marcos, como Spring, tienen formas sencillas de activar el proceso de validación simplemente usando anotaciones. Esto es principalmente para que no tengamos que interactuar con la API de validación programática.
Ahora vayamos por la ruta manual y configuremos las cosas mediante programación:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();
Para validar un bean, primero necesitamos un objeto Validator , que se construye usando un ValidatorFactory .
5.1. Definiendo el Bean
Ahora vamos a configurar este usuario no válido, con un valor de nombre nulo :
User user = new User(); user.setWorking(true); user.setAboutMe("Its all about me!"); user.setAge(50);
5.2. Validar el Bean
Ahora que tenemos un Validator , podemos validar nuestro bean pasándolo al método validate .
Cualquier violación de las restricciones definidas en el objeto Usuario se devolverá como un Conjunto :
Set
violations = validator.validate(user);
Al iterar sobre las violaciones, podemos obtener todos los mensajes de violación usando el método getMessage :
for (ConstraintViolation violation : violations) { log.error(violation.getMessage()); }
En nuestro ejemplo ( ifNameIsNull_nameValidationFails ), el conjunto contendría una sola ConstraintViolation con el mensaje "El nombre no puede ser nulo".
6. Conclusión
Este artículo se centró en una simple pasada a través de la API estándar de validación de Java. Mostramos los conceptos básicos de la validación de beans utilizando anotaciones y API javax.validation .
Como de costumbre, una implementación de los conceptos de este artículo y todos los fragmentos de código se pueden encontrar en GitHub.