Validation
RIFE2's validation API centralizes its operations around beans.
You register a series of ValidationRule
s, then validate them against the
current state of your bean, potentially generating a list of ValidationError
s.
Each error applies to a validated property and has a symbolic identifier that
can be inspected.
Most of this is automated through the use of Constraints, which will register appropriate corresponding validation rules.
You can however also work with the validation API directly, let's take a look at how that works.
We'll take a step back and not use constraints for the Person
class in our
ongoing example.
Just adding validation rules could then look like this:
public class Person extends Validation {
private Integer id_;
private String name_;
protected void activateValidation() {
addRule(new ValidationRuleNotNull("name"));
addRule(new ValidationRuleLimitedLength("name", 0, 30));
}
public void setId(Integer id) { id_ = id; }
public Integer getId() { return id_; }
public void setName(String name) { name_ = name; }
public String getName() { return name_; }
}
The person.validate()
call will behave exactly the same as before, but since
no constraints were added, the GenericQueryManager
's database table queries
will not be generated with those in mind.
You can create your own validation rules by implementing the ValidationRule
interface and completely customize a bean's validation logic. Constraints are
provided by RIFE2 as they need to be understood throughout the full stack, so
their customization opportunities are less flexible.
Calling validate()
evaluates the active validation rules and accumulates
validation errors. When validation errors are present, false
will be returned
and the errors can be obtained through getValidationErrors()
.
The previous section about constraints has an example demonstrating this, here are the extracted relevant lines:
var person = c.parametersBean(Person.class);
if (!person.validate()) {
// person is invalid
person.getValidationErrors().forEach(e ->
// do something with each validation error
);
} else {
// person is valid
}
TIP : You can find a complete example of how to use validation in the RIFE2 GitHub repository.
You can also perform any validation logic of your own and add custom validation
errors through addValidationError(ValidationError)
. This allows all the
validation results to end up in one collection that can be handled the same way.
Note: Validation is not reset with you call
validate()
, allowing you to accumulate errors in different contexts. UseresetValidation()
to start validation over for a particular bean instance.
Sometimes rules only apply in certain situations, you could decide to dynamically add different validation rules, but RIFE2 also provides a way to group rules and only validate specific groups.
For instance, imagine that our Person
class also has an email address, but
that it is validated in a second step. These could then be the validation rules:
// ...
protected void activateValidation() {
addGroup("step1")
.addRule(new ValidationRuleNotNull("name"))
.addRule(new ValidationRuleLimitedLength("name", 0, 30));
addGroup("step2")
.addRule(new ValidationRuleNotNull("email"))
.addRule(new ValidationRuleEmail("email"))
.addRule(new ValidationRuleLimitedLength("email", 0, 50));
}
// ...
Note that you can also use constraints this way:
// ...
protected void activateValidation() {
addGroup("step1")
.addConstraint(new ConstrainedProperty("name")
.maxLength(20)
.notNull(true));
addGroup("step2")
.addConstraint(new ConstrainedProperty("email")
.email(true)
.maxLength(50)
.notNull(true));
}
// ...
Groups are currently only used for validation, and you have two options:
- either you only validate the rules for a specific group
- or you focus on the errors that only apply to a specific group
For example, validating a group could look like this:
var person = new Person();
person.validateGroup("step1");
// do something if errors occurred
person.resetValidation();
person.validateGroup("step2");
// do something if errors occurred
And focusing on the errors of a particular group could look like this:
var person = new Person();
person.validate();
person.focusGroup("step1");
// do something if errors occurred
person.resetValidation();
person.validate();
person.focusGroup("step2");
// do something if errors occurred
Next learn more about Error Reporting