openxava / documentación / Lección 18: Validando con @EntityValidator

Curso: 1. Primeros pasos | 2. Modelo básico del dominio (1)  | 3. Modelo básico del dominio (2) | 4. Refinar la interfaz de usuario | 5. Desarrollo ágil | 6. Herencia de superclases mapedas | 7. Herencia de entidades | 8. Herencia de vistas | 9. Propiedades Java | 10. Propiedades calculadas | 11. @DefaultValueCalculator en colecciones | 12. @Calculation y totales de colección | 13. @DefaultValueCalculator desde archivo | 14. Evolución del esquema manual | 15. Cálculo de valor por defecto multiusuario | 16. Sincronizar propiedades persistentes y calculadas | 17. Lógica desde la base de datos | 18. Validando con @EntityValidator19. Alternativas de validación  | 20. Validación al borrar  21. Anotación Bean Validation propia | 22. Llamada REST desde una validación  | 23. Atributos en anotaciones  | 24. Refinar el comportamiento predefinido | 25. Comportamiento y lógica de negocio | 26. Referencias y colecciones | A. Arquitectura y filosofía | B. Java Persistence API | C. Anotaciones | D. Pruebas automáticas

Tabla de contenidos

Lección 18: Validando con @Entity Validator
Nuestra validación
Añadir la propiedad entregado a Pedido
Validar con @EntityValidator
Resumen
De momento solo hemos hecho validaciones básicas usando la anotación @Required de OpenXava. En esta lección vas a aprender a validar usando la anotación @EntityValidator.

Si no te gustan los videos sigue las instrucciones a continuación.

Nuestra validación

Vamos a refinar tu código para que el usuario no pueda asignar pedidos a una factura si los pedidos no han sido entregados todavía. Es decir, solo los pedidos entregados pueden asociarse a una factura. Aprovecharemos la oportunidad para explorar diferentes formas de hacer esta validación.

Añadir la propiedad entregado a Pedido

Para hacer esto, lo primero es añadir una nueva propiedad a la entidad Pedido. La propiedad entregado:
@Column(columnDefinition="BOOLEAN DEFAULT FALSE")
boolean entregado;
Además es necesario añadir la propiedad entregado a la vista. Modifica la vista Pedido como muestra el siguiente código:
@View(extendsView="super.DEFAULT", 
    members=
        "diasEntregaEstimados, entregado, " + // Añade entregado
        "factura { factura }"
)
...
public class Pedido extends DocumentoComercial {
Ahora tienes una nueva propiedad entregado que el usuario puede marcar para indicar que el pedido ha sido entregado. Ejecuta el nuevo código y marca algunos de los pedidos existentes como entregados.

Validar con @EntityValidator

En tu aplicación actual el usuario puede añadir cualquier pedido que le plazca a una factura usando el módulo Factura y puede asignar una factura a cualquier pedido desde el módulo Pedido. Vamos a restringir esto. Solo los pedidos entregados podrán añadirse a una factura.
La primera alternativa que usaremos para implementar esta validación es mediante @EntityValidator. Esta anotación te permite asignar a tu entidad una clase con la lógica de validación deseada. Anotemos tu entidad Pedido tal como muestra el siguiente código:
@EntityValidator(
    value=com.tuempresa.facturacion.validadores.ValidadorEntregadoParaEstarEnFactura.class, // Clase con la lógica de validación
    properties= {
        @PropertyValue(name="anyo"), // El contenido de estas propiedades
        @PropertyValue(name="numero"), // se mueve desde la entidad 'Pedido'
        @PropertyValue(name="factura"), // al validador antes de
        @PropertyValue(name="entregado") // ejecutar la validación
})
public class Pedido extends DocumentoComercial {
Cada vez que un objeto Pedido se crea o modifica un objeto del tipo ValidadorEntregadoParaEstarEnFactura es creado, entonces las propiedades anyo, numero, factura y entregado se rellenan con las propiedades del mismo nombre del objeto Pedido. Después de eso, el método validate() del validador se ejecuta. Escribamos el código del validador, primero crea el paquete com.tuempresa.facturacion.validadores y después pon en él esta clase:
package com.tuempresa.facturacion.validadores; // En el paquete 'validadores'
 
import com.tuempresa.facturacion.modelo.*;
import org.openxava.util.*;
import org.openxava.validators.*;
import lombok.*;
 
@Getter @Setter 
public class ValidadorEntregadoParaEstarEnFactura
    implements IValidator { // ha de implementar 'IValidator'
 
    private int anyo; // Propiedades a ser inyectadas desde Pedido
    private int numero;
    private boolean entregado;
    private Factura factura;
 
    public void validate(Messages errors)
        throws Exception { // La lógica de validación
        if (factura == null) return;
        if (!entregado) {
            errors.add( // Al añadir mensajes a 'errors' la validación fallará
                "pedido_debe_estar_entregado", // Un id del archivo i18n
                anyo, numero); // Argumentos para el mensaje
        }
    }

}
La lógica de validación es extremadamente fácil, si una factura está presente y este pedido no está marcado como entregado, añadimos un mensaje de error, por tanto la validación fallará. Has de añadir el mensaje de error en el archivo facturacion/src/main/resources/i18n/facturacion-messages_es.properties. Tal como muestra a continuación:
# Mensajes  para la aplicación Facturacion
pedido_debe_estar_entregado=Pedido {0}/{1} debe estar entregado para ser añadido a una Factura
Ahora puedes intentar añadir pedidos a una factura con la aplicación, verás como los pedidos no entregados son rechazados. Ve al módulo Facturas, selecciona la pestaña PEDIDOS de una factura y desde ahí pulsa en el botón Añadir:
validation_es010.png
Se mostrará un diálogo con una lista de pedidos para escoger. Selecciona dos, uno de ellos no entregado todavía y pulsa en AÑADIR:
validation_es013.png
Entonces el pedido entregado se añadirá mientras que el otro es rechazado, generando los siguientes mensajes:
validation_es017.png

Resumen

Ya tienes tu validación hecha con @EntityValidator. No es difícil, pero es un poco verboso, porque necesitas escribir una clase nueva solo para añadir 2 líneas de lógica. Esto es un gran avance. En la siguiente lección veremos otras formas más sencillas de efectuar esta misma validación.

Descargar código fuente de esta lección

¿Problemas con la lección? Pregunta en el foro ¿Ha ido bien? Ve a la lección 19