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
En la lección anterior vimos alternativas de validación al grabar. En esta lección vamos a ver como validar al borrar.
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
Order con
@RemoveValidator, como se muestra a continuación:
@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // La clase con la validación
public class Order extends CommercialDocument {
Ahora, antes de borrar un pedido la lógica de
OrderRemoveValidator se ejecuta y si la validación falla el pedido no se borra. Veamos el código de este validador:
package com.yourcompany.invoicing.validators; // En el paquete 'validators'
import com.yourcompany.invoicing.model.*;
import org.openxava.util.*;
import org.openxava.validators.*;
public class OrderRemoveValidator
implements IRemoveValidator { // Ha de implementar 'IRemoveValidator'
private Order order;
public void setEntity(Object entity) // La entidad a borrar se inyectará...
throws Exception // ...con este método antes de la validación
{
this.order = (Order) entity;
}
public void validate(Messages errors) // La lógica de validación
throws Exception
{
if (order.getInvoice() != null) {
// Añadiendo mensajes a 'errors' la validación fallará y el
// borrado se abortará
errors.add("cannot_delete_order_with_invoice");
}
}
}
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
invoicing/src/main/resources/i18n/invoicing-messages_es.properties:
cannot_delete_order_with_invoice=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
Order, en este caso en un método
@PreRemove.
El primer paso es eliminar la clase
OrderRemoveValidator de tu proyecto. Además quita la anotación
@RemoveValidator de tu entidad
Order:
//@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // Quitamos '@RemoveValidator'
public class Order extends CommercialDocument {
Hemos quitado la validación. Añadámosla otra vez, pero ahora dentro de la misma clase
Order. Añade el método
validateOnRemove() a la clase
Order, como se muestra a continuación:
@PreRemove // Justo antes de borrar la entidad
private void validateOnRemove() {
if (invoice != null) { // La lógica de validación
throw new jakarta.validation.ValidationException( // Lanza una excepción runtime
XavaResources.getString( // Para obtener un mensaje de texto
"cannot_delete_order_with_invoice"));
}
}
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!