Reputation: 1479
I've enabled spring mvc annotation driven for my project. The idea is to use @Valid
annotation with spring annotations to avoid the line in the controller like:
validator.validate(form, errors)
I've noticed that this stuff does not work with spring annotations from package:
org.springmodules.validation.bean.conf.loader.annotation.handle
After investigation I've found that I can use annotations from javax
or org.hibernate.validator.constraints
as alternative way.
But unfortunatly, I have some special cases when I cannot achieve this:
@MinSize(applyIf = "name NOT EQUALS 'default'", value = 1)
Will be good to know in which way spring annotation can be used with @Valid
or any other alternative way to avoid refactoring related to applyIf
attributes(Move conditions to java code).
Upvotes: 1
Views: 2267
Reputation: 9179
Here is an example how to create a custom Validator.
At first create your own Annotation:
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = StringValidator.class)
public @interface ValidString {
String message() default "Invalid data";
int min() default -1;
int max() default -1;
String regex() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Then you will need a custom validator:
public class StringValidator implements ConstraintValidator<ValidString, String> {
private int _min;
private int _max;
private String _regex;
private boolean _decode;
public void initialize(ValidString constraintAnnotation) {
_min = constraintAnnotation.min();
_max = constraintAnnotation.max();
_regex = constraintAnnotation.regex();
_decode = constraintAnnotation.decode();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
String test = value.trim();
if (_min >= 0) {
if (test.length() < _min) {
return false;
}
}
if (_max > 0) {
if (test.length() > _max) {
return false;
}
}
if (_regex != null && !_regex.isEmpty()) {
if (!test.matches(_regex)) {
return false;
}
}
return true;
}
}
Finally you can use it in your Beans and Controller:
public class UserForm {
@ValidString(min=4, max=20, regex="^[a-z0-9]+")
private String name;
//...
}
// Method from Controller
@RequestMapping(method = RequestMethod.POST)
public String saveUser(@Valid UserForm form, BindingResult brResult) {
if (brResult.hasErrors()) {
//TODO:
}
return "somepage";
}
Upvotes: 1
Reputation: 26067
Something like this might help you out
public class UserValidator implements Validator {
@Override
public boolean supports(Class clazz) {
return User.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
if(user.getName() == null) {
errors.rejectValue("name", "your_error_code");
}
// do "complex" validation here
}
}
Then in your controller you would have :
@RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, @ModelAttribute("user") User user, BindingResult result){
UserValidator userValidator = new UserValidator();
userValidator.validate(user, result);
if (result.hasErrors()){
// do something
}
else {
// do something else
}
}
If there are validation errors, result.hasErrors()
will be true.
Note : You can also set the validator in a @InitBinder
method of the controller, with "binder.setValidator(...)" . Or you could instantiate it in the default constructor of the controller. Or have a @Component/@Service
UserValidato
r that you inject (@Autowired
) in your controller : very useful, because most validators are singletons + unit test mocking becomes easier + your validator could call other Spring components.
Upvotes: 0