Announcement Announcement Module
Collapse
No announcement yet.
Partially using JSR-303 for validation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Partially using JSR-303 for validation

    Dear Spring community,

    What I am trying to implement is the following:
    • I would like to use JSR-303 @Valid annotation
    • I would like to have a custom validator per controller (via @InitBinder)
    • I would like Spring to call validator.validate() (so not this way)
    • I don't want to include validation implementation (like Hibernate) into classpath.

    I basically follow the steps mentioned here:
    • I add javax.validation.validation-api:validation-api as my dependency
    • I use <mvc:annotation-driven />
    • I mark my model with @Valid:
      public String onRegistrationFormSubmitted(@ModelAttribute("regis trationForm") @Valid RegistrationForm registrationForm, BindingResult result) ...

    So what happens, is that validation API tries to locate any implementation and fails:

    Code:
    Caused by: javax.validation.ValidationException: Unable to find a default provider
    	at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:264)
    	at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:183)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
    The way out is to define a validator property for AnnotationDrivenBeanDefinitionParser:

    Code:
    <bean name="validator" class="org.company.module.RegistrationFormValidator" />
    
    <mvc:annotation-driven validator="validator" />
    but this approach means that the validator will be set to all controllers by ConfigurableWebBindingInitializer.initBinder().

    I understand that I am trying to use the framework in a special way, but what the community will say, if there is a special meaning for validator property which tells that validator does not need to be resolved, e.g.

    Code:
    <mvc:annotation-driven validator="manual" />
    with special treatment:

    Code:
    --- AnnotationDrivenBeanDefinitionParser.java.orig      2011-06-30 14:33:10.287577300 +0200
    +++ AnnotationDrivenBeanDefinitionParser.java   2011-06-30 14:34:27.897449000 +0200
    @@ -152,6 +152,10 @@
    
            private RuntimeBeanReference getValidator(Element element, Object source, ParserContext parserContext) {
                    if (element.hasAttribute("validator")) {
    +                       if ("manual".equals(element.getAttribute("validator"))) {
    +                               return null;
    +                       }
    +
                            return new RuntimeBeanReference(element.getAttribute("validator"));
                    }
                    else if (jsr303Present) {
    Any feedback is welcomed.

  • #2
    Hi dma_k,


    I came across your post because I've noticed the exact same problem.

    The only "work around" I found was to implement my own @Valid annotation, once Spring (at least in 3.1.1.RELEASE code base) only checks the method argument annotation's simple name (please look into the org.springframework.web.method.annotation.ModelAtt ributeMethodProcessor class below). This way, I don't need to add javax.validation.validation-api:validation-api to my project's dependencies and I stop getting the infamous javax.validation.ValidationException: Unable to find a default provider.



    Code:
    /**
     * Validate the model attribute if applicable.
     * <p>The default implementation checks for {@code @javax.validation.Valid}.
     * @param binder the DataBinder to be used
     * @param parameter the method parameter
     */
    protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
    	Annotation[] annotations = parameter.getParameterAnnotations();
    	for (Annotation annot : annotations) {
    		if (annot.annotationType().getSimpleName().startsWith("Valid")) {
    			Object hints = AnnotationUtils.getValue(annot);
    			binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
    		}
    	}
    }

    It's been a long time since you opened this topic, but I hope it helps.
    Last edited by mhnagaoka; Apr 13th, 2012, 06:15 AM.

    Comment


    • #3
      Hi,

      Thanks for the info. Really interesting workaround. I've posted the question to stackoverflow: could you re-post your answer there?

      Comment


      • #4
        Originally posted by dma_k View Post
        Hi,

        Thanks for the info. Really interesting workaround. I've posted the question to stackoverflow: could you re-post your answer there?
        Done (http://stackoverflow.com/a/10272765/710780)

        Comment

        Working...
        X