openxava / documentación / Lección 20: Validación al borrar

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 @EntityValidator | 19. 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 20:Validación al borrar
Validar al borrar con @RemoveValidator
Validar al borrar con un método de retrollamada
¿Cuál es la mejor forma de validar?
Resumen
En la lección anterior vimos alternativas de validación al grabar. En esta lección vamos a ver como validar al borrar.
Si no te gustan los videos sigue las instrucciones a continuación.

Validar al borrar con @RemoveValidator

Las validaciones que hemos visto hasta ahora se hacen cuando la entidad se modifica, pero a veces es útil hacer la validación justo al borrar la entidad y usar la validación para vetar el borrado de la misma.
Vamos a modificar la aplicación para impedir que un usuario borre un pedido si éste tiene una factura asociada. Para hacer esto anota tu entidad Pedido con @RemoveValidator, como se muestra a continuación:
@RemoveValidator(com.tuempresa.facturacion.validadores.ValidadorBorrarPedido.class) // La clase con la validación
public class Pedido extends DocumentoComercial {
Ahora, antes de borrar un pedido la lógica de ValidadorBorrarPedido se ejecuta y si la validación falla el pedido no se borra. Veamos el código de este validador:
package com.tuempresa.facturacion.validadores; // En el paquete 'validadores'
 
import com.tuempresa.facturacion.modelo.*;
import org.openxava.util.*;
import org.openxava.validators.*;
 
public class ValidadorBorrarPedido
    implements IRemoveValidator { // Ha de implementar 'IRemoveValidator'
 
    private Pedido pedido;
 
    public void setEntity(Object entity) // La entidad a borrar se inyectará...
        throws Exception // ...con este método antes de la validación
    {
        this.pedido = (Pedido) entity;
    }
 
    public void validate(Messages errors) // La lógica de validación
        throws Exception
    {
        if (pedido.getFactura() != null) {
            // Añadiendo mensajes a 'errors' la validación fallará y el
            // borrado se abortará
            errors.add("no_puede_borrar_pedido_con_factura");
        }
    }
}
La lógica de validación está en el método validate(). Antes de llamarlo la entidad a validar es inyectada usando setEntity(). Si se añaden mensajes al objeto errors la validación fallará y la entidad no se borrará. Has de añadir el mensaje de error en el archivo facturacion/src/main/resources/i18n/facturacion-messages_es.properties:
no_puede_borrar_pedido_con_factura=Pedido asociado a factura no puede ser eliminado
Ahora si intentas borrar un pedido con una factura asociada obtendrás un mensaje de error y el borrado no se producirá.
Puedes ver que usar un @RemoveValidator no es difícil, pero es un poco verboso. Has de escribir una clase nueva solo para añadir un simple if. Examinemos una alternativa más breve.

Validar al borrar con un método de retrollamada

Vamos a probar otra forma más simple de hacer esta validación al borrar, moviendo la lógica de validación desde la clase validador a la misma entidad Pedido, en este caso en un método @PreRemove.
El primer paso es eliminar la clase ValidadorBorrarPedido de tu proyecto. Además quita la anotación @RemoveValidator de tu entidad Pedido:
// @RemoveValidator(com.tuempresa.facturacion.validadores.ValidadorBorrarPedido.class) // Quitamos '@RemoveValidator'
public class Pedido extends DocumentoComercial {
Hemos quitado la validación. Añadámosla otra vez, pero ahora dentro de la misma clase Pedido. Añade el método validarPreBorrar() a la clase Pedido, como se muestra a continuación:
@PreRemove
private void validarPreBorrar() {
    if (factura != null) { // La lógica de validación
        throw new javax.validation.ValidationException( // Lanza una excepción runtime
            XavaResources.getString( // Para obtener un mensaje de texto
                "no_puede_borrar_pedido_con_factura"));
    }
}
Antes de borrar un pedido esta validación se efectuará, si falla se lanzará una ValidationException. Puedes lanzar cualquier excepción runtime para abortar el borrado. Tan solo con un método dentro de la entidad tienes la validación hecha.

¿Cuál es la mejor forma de validar?

Has aprendido varias formas de hacer la validación sobre tus clases del modelo. ¿Cuál de ellas es la mejor? Todas ellas son opciones válidas. Depende de tus circunstancias y preferencias personales. Si tienes una validación que no es trivial y es reutilizable en varios puntos de tu aplicación, entonces usar un @EntityValidator y @RemoveValidator es una buena opción. Por otra parte, si quieres usar tu modelo fuera de OpenXava y sin JPA, entonces el uso de la validación en los setters es mejor.
En nuestro caso particular hemos optado por @AssertTrue para la validación “el pedido ha de estar servido para estar en una factura” y por @PreRemove para la validación al borrar. Ya que son las alternativas más simples que funcionan.

Resumen

En esta lección has aprendido varias formas de hacer validación al borrar en una aplicación OpenXava. En la siguiente lección vas a ver como crear una anotación Bean Validation propia. ¡Esto puede llegar a ser muy útil!

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 21