Course:
1. Getting started |
2. Basic domain model (1) |
3. Basic domain model (2) |
4. Refining the user interface |
5. Agile development |
6. Mapped superclass inheritance |
7. Entity inheritance |
8. View inheritance |
9. Java properties |
10. Calculated properties |
11. @DefaultValueCalculator in collections |
12. @Calculation and collections totals |
13. @DefaultValueCalculator from file |
14. Manual schema evolution |
15. Multi user default value calculation |
16. Synchronize persistent and computed propierties |
17. Logic from database |
18. Validating with @EntityValidator |
19. Validation alternatives |
20. Validation on remove |
21. Custom Bean Validation annotation |
22. REST service call from validation |
23. Attributes in annotations |
24. Refining the standard behavior |
25. Behavior & business logic |
26. References & collections |
A. Architecture & philosophy |
B. Java Persistence API |
C. Annotations |
D. Automated testing
In the last lesson we looked at validation alternatives to perform on save. In this lesson we are going to look at validation on remove.

If you don't like videos follow the instructions below.
Validating on removal with @RemoveValidator
The validations we have seen until now are processed when the entity is modified, but sometimes it's useful or it's required to process the validation before the removal of the entity, and to use the validation to cancel the entity removal.
We are going to modify the application to reject the removal of an order if it has an invoice associated. To achieve this annotate your
Order entity with
@RemoveValidator, as show in following code:
@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // The class with the validation
public class Order extends CommercialDocument {
Now, before removing an order the logic in
OrderRemoveValidator is executed, and if validation fails the order is not removed. Let's look at the code for the validator:
package com.yourcompany.invoicing.validators; // In 'validators' package
import com.yourcompany.invoicing.model.*;
import org.openxava.util.*;
import org.openxava.validators.*;
public class OrderRemoveValidator
implements IRemoveValidator { // Must implement IRemoveValidator
private Order order;
public void setEntity(Object entity) // The entity to remove will be injected
throws Exception // with this method before validating
{
this.order = (Order) entity;
}
public void validate(Messages errors) // The validation logic
throws Exception
{
if (order.getInvoice() != null) {
// By adding messages to errors the validation
// will fail and the removal will be aborted
errors.add("cannot_delete_order_with_invoice");
}
}
}
The validation logic is in the
validate() method. Before calling the entity to be validated, it is injected using
setEntity(). If messages are added to the
errors object the validation will fail and the entity will not be removed. You have to add the error message in the
invoicing/src/main/resources/i18n/invoicing-messages_en.properties file:
cannot_delete_order_with_invoice=An order with an invoice cannot be deleted
If you try to remove an order with an associated invoice now, you will get an error message and the removal will be rejected.
You can see that using a
@RemoveValidator is not difficult but verbose. You have to write a full new class to add a simple if. Let's examine a briefer alternative.
Validating on removal with a JPA callback method
We're going to try another, maybe simpler, way to do this removal validation just by moving the validation logic from the validator class to the
Order entity itself, in this case in a
@PreRemove method.
First, remove the
OrderRemoveValidator class from your project. Also remove the
@RemoveValidator annotation from your
Order entity:
//@RemoveValidator(com.yourcompany.invoicing.validators.OrderRemoveValidator.class) // Remove the @RemoveValidator
public class Order extends CommercialDocument {
We have just removed the validation. Let's add the functionality again, but now inside the
Order class itself. Add the
validateOnRemove() method in your
Order class:
@PreRemove // Just before removing the entity
private void validateOnRemove() {
if (invoice != null) { // The validation logic
throw new javax.validation.ValidationException( // Throws a runtime exception
XavaResources.getString( // To get the text message
"cannot_delete_order_with_invoice"));
}
}
This validation will be processed before the removal of an order. If it fails a
ValidationException is thrown. You can throw any runtime exception in order to abort the removal. You have done the validation with a single method inside the entity.
What's the best way of validating?
You have learned several ways to do validations in your model classes. Which of them is the best one? All of them are valid options. It depends on your circumstances and personal preferences. If you have a validation that is non-trivial and reusable across your application, then to use
@EntityValidator and
@RemoveValidator is a good option. On the other hand, if you want to use your model classes from outside OpenXava and without JPA, then the use of validation in setters is better.
In our example we'll use the
@AssertTrue for the “delivered to be in invoice” validation and
@PreRemove for the removal validation, because this is the simplest procedure.
Summary
In this lesson you have learned several ways to do validation in an OpenXava application. In the next lesson you are going to learn how to create your own custom bean validation.This can actually be very useful!