Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

springmvc jsr303 validator co-exist with spring WebDataBinder validator in one action

Since springmvc 3.x now supports jsr303 and old spring style validator, i want to mix them in my sample apps. But there is only one method enabled for a specified controller, is that the limit of spring framework or JSR standard?

Here is my sample code.

User.java, stands for the domain model, uses JSR303 for validation.

public class User{
    @Size(max = 16, message = "user loginId max-length is 16")
    private String loginId;
    //omit getter and setter
}

UserValidator.java, implements the org.springframework.validation.Validator interface to support user validation.

public class UserValidator implements Validator {

    private UserService userService;
    public boolean supports(Class<?> clazz) {
        return User.class.isAssignableFrom(clazz);
    }

    public void validate(Object target, Errors errors) {
            User u = (User) target;

            // loginName check for new user
            if (u.getUserId() == null && !userService.isLoginIdUnique(u.getLoginId(), null)) {
                    errors.rejectValue("loginId", "user.loginId.unique", new Object[] { u.getLoginId() }, null);
            }
    }

    @Autowired
    public void setUserService(UserService userService) {
            this.userService = userService;
    }

}

UserController.java, uses InitBinder annotation to inject UserValidator into WebDataBinder.

@Controller("jspUserController")
@RequestMapping("/sys/users")
public class UserController {
    private UserValidator userValidator;

    @Autowired
    public void setUserValidator(UserValidator userValidator) {
        this.userValidator = userValidator;
    }

/*@InitBinder("user")
    public void initBinderUser(WebDataBinder binder) {
        binder.setValidator(userValidator);
    }*/

    @RequestMapping(value = "/save")
    public String save(@Valid User user, BindingResult bindingResult, Model model, HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
            return "/sys/user/edit";
        }
        userService.saveUser(user);
        return "redirect:/sys/users/index";
    }
}

If I uncomment the @InitBinder("user") in UserController, the JSR303 validation will be disabled. While the current commented code will use JSR validator to do the validation. Can anyone give me a workaround to mix them in one controller?

like image 736
Bigfei Avatar asked Jan 11 '12 12:01

Bigfei


2 Answers

You can ADD your validator instead of SETTING it :

@InitBinder("user")
public void initBinderUser(WebDataBinder binder) {
    binder.addValidators(userValidator);
}

This will execute the JSR303 validations first and then your custom validator. No need then to call the validator directly in the save method.

like image 179
wesker317 Avatar answered Nov 15 '22 10:11

wesker317


You can use your validator directly and let the global LocalValidatorFactoryBean (JSR-303) do its work as well:

    @Controller("jspUserController")
    @RequestMapping("/sys/users")
    public class UserController {
        private UserValidator userValidator;

        @Autowired
        public void setUserValidator(UserValidator userValidator) {
            this.userValidator = userValidator;
        }

        @RequestMapping(value = "/save")
        public String save(@Valid User user, BindingResult bindingResult, Model model, HttpServletRequest request) {
            this.userValidator.validate(user, bindingResult);
            if (bindingResult.hasErrors()) {
                return "/sys/user/edit";
            }
            userService.saveUser(user);
            return "redirect:/sys/users/index";
        }
    }
like image 22
Rossen Stoyanchev Avatar answered Nov 15 '22 11:11

Rossen Stoyanchev