I am trying to perform validation using Spring validation. I am wondering what is the best practice to perform validation that depends mainly on user's action, hereafter, I have three different approaches but I don't know which one is best.
Assume, we have the following class Foo to validate and many different rules of validation depending on action performed by user.
public class Foo {
private String name;
private int age;
private String description;
private int evaluation;
// getters, setters
}
What is the best way to perform these validations (for instance: during creation only name and age are required, during evaluate action, I only need evaluation to be validated and so on)
solution 1: one validator class per validation rule
public class CreateFooValidator implements Validator {
//validation for action create
}
public class EvaluateFooValidator implements Validator {
//validation for evaluate action
}
solution 2: one validator class with several methods
public class FooValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Foo.class.equals(clazz);
}
//the default validate method will be used to validate during create action
@Override
public void validate(Object target, Errors errors) {
//validation required
}
//method to validate evaluate action
public void validateFooEvaluation(Object target, Errors errors) {
//validation required
}
//other validation methods for other actions
}
solution 3: Additional property action in class Foo, one validator
public class Foo {
private String name;
private int age;
private String description;
private int evaluation;
private String actionOnFoo;
// getters, setters
}
public class FooValidator implements Validator {
private final Foo foo = (Foo) target;
@Override
public boolean supports(Class<?> clazz) {
return Foo.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
//test which action is performed by user
if ("create".equals(foo.getActionOnFoo())) {
//call for private method that performs validation for create action
}
}
//all private methods
}
What is the best solution among the 3 or other solution if any? Thanks!
Use JSR-303 Validation Groups, which are since Spring MVC 3.1 also supported by @Validated
.
So, for each action you should have a method in your controller. Create a validation group for each possible action that has a different set of rules, e.g.
public interface Create {
}
public interface Evaluate {
}
Annotate Foo
with the validation annotations including the group, e.g.
public class Foo {
@NotNull(groups = { Create.class, Evaluate.class })
private String name;
...
@Min(value = 1, message = "Evaluation value needs to be at least 1", groups = { Evaluate.class })
private int evaluation;
...
}
Then annotate the foo
argument of your controller methods with the appropriate @Validated
annotation, e.g. @Validated({Evaluate.class})
for the evaluate
controller method.
You can find another example here (see item 2): http://blog.goyello.com/2011/12/16/enhancements-spring-mvc31/
Update:
Alternatively, if for some reason you can't / don't want to use @Validated
, you can use an injected Validator
instance and pass the groups to its validate
method. That's the way it was done before Spring 3.1 (as is the case in the article in your comment).
Depends that you want to do it. All solutions are good if you apply in all of your validators the same and you want to validate some business logic, not only if it's null or not (for this purpose you can use the @Valid annotation and annotation @Not null in your objects).
For me, if I have an object Foo I only want one Validator for this object, and then I have several methods for validate the data depends of I need in my controllers, for example, one for saving new Foo or other one for validating before updating, etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With