Hibernate Validator, custom ResourceBundleLocator and Spring

前端 未结 3 1553
忘了有多久
忘了有多久 2020-12-13 22:11

I\'m trying to override default ResourceBundleLocator in hibernate validation 4.1. So far it works perfectly, but the only examples of its usage include java code to instant

相关标签:
3条回答
  • 2020-12-13 22:51

    The magic method that does the required job is LocalValidatorFactoryBean#setValidationMessageSource(MessageSource messageSource).

    First of all, contract of the method:-

    Specify a custom Spring MessageSource for resolving validation messages, instead of relying on JSR-303's default "ValidationMessages.properties" bundle in the classpath. This may refer to a Spring context's shared "messageSource" bean, or to some special MessageSource setup for validation purposes only.

    NOTE: This feature requires Hibernate Validator 4.1 or higher on the classpath. You may nevertheless use a different validation provider but Hibernate Validator's ResourceBundleMessageInterpolator class must be accessible during configuration.

    Specify either this property or "messageInterpolator", not both. If you would like to build a custom MessageInterpolator, consider deriving from Hibernate Validator's ResourceBundleMessageInterpolator and passing in a Spring MessageSourceResourceBundleLocator when constructing your interpolator.

    You can specify your custom message.properties(or .xml) by invoking this method... like this...

    my-beans.xml

    <bean name="validator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource">
            <ref bean="resourceBundleLocator"/>
        </property>
    </bean>
    
    <bean name="resourceBundleLocator" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>META-INF/validation_errors</value>
            </list>
        </property>
    </bean>
    

    validation_errors.properties

    javax.validation.constraints.NotNull.message=MyNotNullMessage
    

    Person.java

        class Person {
        private String firstName;
        private String lastName;
    
        @NotNull
        public String getFirstName() {
            return firstName;
        }
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
        public String getLastName() {
            return lastName;
        }
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    }
    

    BeanValidationTest.java

        public class BeanValidationTest {
    
        private static ApplicationContext applicationContext; 
    
        @BeforeClass
        public static void initialize() {
            applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring/webmvc-beans.xml");
            Assert.assertNotNull(applicationContext);
        }
    
        @Test
        public void test() {
            LocalValidatorFactoryBean factory = applicationContext.getBean("validator", LocalValidatorFactoryBean.class);
            Validator validator = factory.getValidator();
            Person person = new Person();
            person.setLastName("dude");
            Set<ConstraintViolation<Person>> violations = validator.validate(person);
            for(ConstraintViolation<Person> violation : violations) {
                System.out.println("Custom Message:- " + violation.getMessage());
            }
        }
    
    }
    

    Outupt: Custom Message:- MyNotNullMessage

    0 讨论(0)
  • 2020-12-13 23:02

    Thank you @Lu55, based on your answer I solved my problem!!

    I just converted to a Configuration class, and I am posting here just in case anyone else need:

    Import detail: it worked for me with ReloadableResourceBundleMessageSource, but it did not work using ResourceBundleMessageSource. I am not sure why.

    @Configuration
    public class ErrorConfig {
    
        @Bean
        public Validator validatorFactory (MessageSource messageSource) {
            LocalValidatorFactoryBean validator =  new LocalValidatorFactoryBean();
            validator.setValidationMessageSource(messageSource);
            return validator;
        }
    
        @Bean
        public MessageSource messageSource() {
            ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
            bean.addBasenames("classpath:org.hibernate.validator.ValidationMessages","classpath:message");
            bean.setDefaultEncoding("UTF-8");
            return bean;
        }
    }
    

    Inside my resource folder I have message.properties file.

    0 讨论(0)
  • 2020-12-13 23:10

    Here is a solution if you want to mix the existing hibernate validation messages and custom validation messages :

    <mvc:annotation-driven validator="validator" />
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="i18n,iso-i18n,org.hibernate.validator.ValidationMessages" />
        <property name="useCodeAsDefaultMessage" value="true" />
    </bean>
    

    (see Web MVC framework Validation section and Configuring a Bean Validation Provider in Spring documentation)

    0 讨论(0)
提交回复
热议问题