On Play! Framework 2.6 I have implemented the following form which requires a custom validation:
@Validate
public class MachineRegistrationForm implements Validatable<List<ValidationError>> {
@Required
private String field1;
@Required
private String field2;
// other fields, getters and setters
@Override
public List<ValidationError> validate() {
// validation on field1 and field2
}
}
Looks like Play performs my custom validation before checking if the @Required fields field1 and field2 actually contains some values, forcing me to check if the values are null to avoid NullPointerExceptions. Am I following the wrong approach to custom validation or is this a Play! unintended behaviour?
TLDR: RTFM ;-)
In your example the validate()
method is not evaluated before the two @Required
constraints: The three constraints are called simultaneously - so basically there is no guaranteed order what will run first. This is also documented in the Play Framework documentation :
Also be aware that in this example the
validate
method and the@Constraints.Required
constraint will be called simultaneously - so the validate method will be called no matter if@Constraints.Required
was successful or not (and vice versa). You will learn how to introduce an order later on.
If you carefully read the docs you will then find the section "Defining the order of constraint groups" :
You can validate groups in sequences. This means groups will be validated one after another - but the next group will only be validated if the previous group was validated successfully before. (However right now it's not possible to determine the order of how constraints will be validated within a group itself...)
To make that work for you example let's great the group...
public interface First { }
...and...
public interface Second { }
...and you would have to great following group sequence:
import javax.validation.GroupSequence;
import javax.validation.groups.Default;
@GroupSequence({ Default.class, First.class, Second.class })
public interface OrderedChecks { }
Then you have to add the groups to your constraints:
@Validate(groups = {Second.class})
public class MachineRegistrationForm implements Validatable<List<ValidationError>> {
@Required // Default group is Default.class
private String field1;
@Required(groups = {First.class})
private String field2;
// other fields, getters and setters
@Override
public List<ValidationError> validate() {
// validation on field1 and field2
}
}
Now you can trigger the validation with the defined order:
Form<MachineRegistrationForm> form = formFactory().form(MachineRegistrationForm.class, OrderedChecks.class).bindFromRequest();
Now field1
will be checked first and only if it succeeded then field2
will be checked and only if that one succeeded as well the validate
method will be checked. You could also remove (groups = {First.class})
from field2
(so it has the Default.class
group by default as well) or , the other way around, add (groups = {First.class})
to field1
- in both cases now the two fields would be evaluated simultaneously - and only if both succeed then validate
would be evaluted.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.