I have a spring 3 controller with a validator for one of the methods. It insists on validating every object on the model. Would anyone be able to explain to me why it does this or if I'm doing something wrong?
According to the docs, 5.7.4.3 Configuring a JSR-303 Validator for use by Spring MVC (http://static.springsource.org/spring/docs/3.0.0.RC3/spring-framework-reference/html/ch05s07.html)
With JSR-303, a single javax.validation.Validator instance typically validates all model objects that declare validation constraints. To configure a JSR-303-backed Validator with Spring MVC, simply add a JSR-303 Provider, such as Hibernate Validator, to your classpath. Spring MVC will detect it and automatically enable JSR-303 support across all Controllers.
Example:
@Controller public class WhaleController { @Autowired private Validator myValidator; @Autowired private WhaleService whaleService; @InitBinder protected void initBinder(WebDataBinder binder) { binder.setValidator(this.myValidator); } @RequestMapping(value="/save-the-whales") @Transactional public void saveTheWhales(@Valid WhaleFormData formData, BindingResult errors, Model model) { if (!errors.hasFieldErrors()) { Whale whale = new Whale(); whale.setBreed( formData.getBreed() ); this.whaleService.saveWhale( whale ); model.addAttribute("whale", whale); } model.addAttribute("errors", errors.getFieldErrors()); } }
When run it will complain that Whale is an invalid target for myValidator (which is set to validate WhaleFormData, and does so fine). Whale is a POJO with no validation constraints, annotation and no config anywhere. Through trial and error I've found that ANY object placed on the model will attempt to be validated and fail if the validator is not setup to handle it. Primitives are just fine.
Can anyone tell me why this is, point me to the appropriate documentation and/or tell me the best way to put something on the model without having it validated?
In the case above I would like to place "whale" on the model as it will now have a unique whaleId() that it received from my persistence layer.
Thanks!
The @Validated annotation is a class-level annotation that we can use to tell Spring to validate parameters that are passed into a method of the annotated class.
The @Valid annotation will tell spring to go and validate the data passed into the controller by checking to see that the integer numberBetweenOneAndTen is between 1 and 10 inclusive because of those min and max annotations.
I guess this behaviour is not covered in the documentation well.
The problem is caused by the following:
By default, @InitBinder
-annotated method is called for each non-primitive model attribute, both incoming and outcoming (the purpose of calling it for outcoming attibutes is to allow you to register custom PropertyEditor
s, which are used by form tags when rendering a form).
DataBinder.setValidator()
contains a defensive check that call Validator.supports()
and throws an exception if false
is returned. So, there is no attempt to perform a validation, just an early check.
The solution is to restrict the scope of @InitBinder
to particular attribute:
@InitBinder("whaleFormData") protected void initBinder(WebDataBinder binder) { ... }
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