Announcement Announcement Module
Collapse
No announcement yet.
Extending JSR-303 validation: "validate" is not invoked by @Valid annotation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Extending JSR-303 validation: "validate" is not invoked by @Valid annotation

    Hello,

    I am using Spring 3.1.4 and Hibernate Validator 4.3.1. I've already read the following two threads, both dealing with mixing JSR-303 and (custom) Spring Validation:

    I want my custom validator automatically beeing used when annotating a parameter with the @Valid annotation within a @Controller (plus using JSR-303 "Bean Validation"). Here is my source code:

    Entity:
    Code:
    @Entity
    public class LoginUser {
        @NotNull
        private String username;
    }
    Controller:
    Code:
    @Controller
    public class LoginUserController {
    
    	Logger log = LoggerFactory.getLogger(this.getClass());
    
    	@Autowired
    	private Validator loginUserValidator;
    
    	@InitBinder
    	protected void initBinder(final WebDataBinder binder) {
    		this.log.info("initBinder");
    		binder.setValidator(loginUserValidator);
    	}
    
    	@RequestMapping(method = RequestMethod.POST, produces = "text/html")
    	public String create(
    		@Valid @ModelAttribute("loginUser") LoginUser loginUser,
    		BindingResult bindingResult, Model uiModel,
    		HttpServletRequest httpServletRequest
    	) {
    		this.log.info("create");
    		return "redirect:/";
    	}
    }
    Validator:
    Code:
    @Component
    public class LoginUserValidator
    	extends LocalValidatorFactoryBean
    	implements Validator
    {
    	Logger log = LoggerFactory.getLogger(this.getClass());
    
    	@Override
    	public boolean supports(final Class<?> clazz) {
    		this.log.info("supports");
    		return LoginUser.class.equals(clazz);
    	}
    
    	@Override
    	public void validate(final Object target, final Errors errors) {
    		this.log.info("is not called");
    		super.validate(target, errors);
    	}
    
    	@Override
    	public void validate(final Object target, final Errors errors, final Object... validationHints) {
    		this.log.info("is called");
    		super.validate(target, errors, validationHints);
    	}
    }
    The logger output shows that the methods "supports" and "initBinder" are called. But the validator does not seem to be triggered via the @Valid annotation (therefore the "validate" method is not called).

    I also do have the following line in the webmvc-config.xml file:
    Code:
    <mvc:annotation-driven conversion-service="applicationConversionService"/>
    I am really confused, because in the other two threads mentioned above, this seems to be the proper solution to mix both validations. I do not want to call the "validate" method, but use the @Valid annotation instead!

    Edit: I've just discovered http://stackoverflow.com/questions/1...bean-in-spring describing the same problem. What is the prefered ("best"( way to achieve, what I want to achieve then with Spring 3.1?
    Edit: I've updated the source code above. The "validate" method with three arguments is invoked and the default behaviour seems to have changed from version 3.0 to version 3.1. I will simply use the method with three arguments. But in my opinion this is black magic and does not seem to be documented.
    Last edited by teh_hahn; Feb 9th, 2013, 01:37 PM. Reason: Added note about solution.

  • #2
    How do you check validation error in your code??? I expected to see something like:
    Code:
    @RequestMapping(method = RequestMethod.POST, produces = "text/html")
    public String create(
    		@Valid @ModelAttribute("loginUser") LoginUser loginUser,
    		BindingResult bindingResult, Model uiModel,
    		HttpServletRequest httpServletRequest
    	) {
            if (bindingResult.hasErrors()) {
                return "loginView"; // return to your login page
            }
            .......... // rest of logic
    }

    Comment


    • #3
      Yes, I do have that code in my controller. I've shortened it as much as possible. I already found the solution: Using the "validate" method with three arguments over the one with two arguments. The question is: Why this behaviour?! It does not make sense at all imho.

      Comment

      Working...
      X