Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring JSR303 validation doesn't work like described in Spring Documentation

I tried implementing validation for my web application like described in section 5.7.4.3 of the Spring 3.0 documentation:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator">
                <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
            </property>
        </bean>
    </property>
</bean>

I've added hibernate-validator as a dependency and everything looks OK, but starting my web app results in the following error:

org.springframework.beans.NotWritablePropertyException:
Invalid property 'validator' of bean class
[org.springframework.web.bind.support.ConfigurableWebBindingInitializer]:
Bean property 'validator' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?

When looking at the API it's pretty obvious that something's wrong. LocalValidatorFactoryBean implements javax.validation.Validator while ConfigurableWebBindingInitializer.setValidator() expects a org.springframework.validation.Validator.

Any solution for this?

EDIT

About LocalValidatorFactoryBean:

This is the central class for javax.validation (JSR-303) setup in a Spring application context: It bootstraps a javax.validation.ValidationFactory and exposes it through the Spring Validator interface as well as through the JSR-303 Validator interface and the ValidatorFactory interface itself.

Like Alex Marshall stated below this is not the case. LocalValidatorFactoryBean only implements javax.validation.Validator.

LocalValidatorFactoryBean does extend SpringValidatorAdapter though, which implements org.springframework.validation.Validator.

like image 820
Koraktor Avatar asked Oct 02 '09 11:10

Koraktor


2 Answers

Here's a workaround for this issue:

Using the validator bean configuration from my question above you have to add the following code in each controller using validation.

@Autowired
private javax.validation.Validator validator;

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.setValidator((org.springframework.validation.Validator) this.validator);
}

It's dirty, but it works because LocalValidatorFactoryBean extends SpringValidatorAdapter and this implements org.springframework.validation.Validator.

like image 126
Koraktor Avatar answered Sep 18 '22 00:09

Koraktor


If you look at the Javadocs for ConfigurableWebBindingInitializer, its property 'validator' is of type 'org.springframework.validation.Validator'. If you then look at the Javadocs for LocalValidatorFactoryBean, you'll see that it actually implements neither FactoryBean (to create an org.springframework.validation.Validator) nor does it implement org.springframework.validation.Validator itself, so the bean you're giving the 'validator' property of ConfigurableWebBindingInitializer is of the wrong type, as indicated by the error. I suspect this is a (gross?) oversight on the part of the Spring developers, and you should create an issue for this in their JIRA issue tracker at jira.springframework.org

like image 25
Alex Marshall Avatar answered Sep 18 '22 00:09

Alex Marshall