JDC
JDC

Reputation: 4385

Spring Data REST(using Spring Boot) - Hibernate Validation Localization

I am currently evaluating Spring Data REST.
I started with this simple example: link

It works out of the box. But now, in the next step, I wanted to try some validation to see how the framework reacts. So I simply annotated the Personclass:

@Size(min = 2, message = "{test.error.message}")
private String firstName;

The validation itself is working, I get an error message. The message is resolved if I put a file called ValidationMessages.properties in the root of the classpath (see here why).


Now, instead of having the files in the root I wanted to place them in a subfolder (e.g. lang/ValidationMessages.properties) and use Spring MessageSource instead of the default approach.

After some research I found the following question: MessageInterpolator in Spring

Unfortunately using the following bean definitions does not work:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

  <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
      <list>
        <value>lang/ValidationMessages</value>
      </list>
    </property>
  </bean>

  <bean id="validator"
            class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource" ref="messageSource"/>
  </bean>
</beans>

The corresponding dependencies inside the pom.xml (just in case):

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Does anyone know what I am missing? Could it be due to the fact that I am not using Spring MVC but Spring Data REST? If yes, is there a way of getting this to work?

Upvotes: 2

Views: 1604

Answers (2)

shenyu1997
shenyu1997

Reputation: 640

HibernateJpaAutoConfiguration can not work anymore (after sprint boot 2.10)

You can do like this if you are using Spring Boot 2.1.0+:

@Configuration
@Lazy
class SpringValidatorConfiguration {

    @Bean
    @Lazy
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(final Validator validator) {
        return new HibernatePropertiesCustomizer() {

            @Override
            public void customize(Map<String, Object> hibernateProperties) {
                hibernateProperties.put("javax.persistence.validation.factory", validator);
            }
        };
    }
}

The idea from Spring Boot 2.0.0 M6 - Add Hibernate Interceptor

and Spring Boot - Hibernate custom constraint doesn't inject Service

Upvotes: 3

JDC
JDC

Reputation: 4385

After some additional investigation (and a lot of searching) I found a solution to the issue.


PROBLEM

Hibernate does not use beans for the validator factory, thats why the LocalValidatorFactoryBean is not used.

For more details look into org.hibernate.cfg.beanvalidation.TypeSafeActivator#activate(ActivationContext activationContext)


FIRST APPROACH

You can actually specify which factory to use by using this property: javax.persistence.validation.factory

Unfortunately this can't be used (yet) inside Spring Boot's application.properties.
(see this Issue on GitHub)


SOLUTION

Using the workaround described in the linked GitHub issue works. You have to provide a configuration for Hibernate:

@Configuration
public class HibernateConfig extends HibernateJpaAutoConfiguration {

  @Autowired
  private ValidatorFactory validator;

  @Override
  protected void customizeVendorProperties(Map<String, Object>     vendorProperties) {
    super.customizeVendorProperties(vendorProperties);
    vendorProperties.put("javax.persistence.validation.factory", validator);
  }
}

Using this approach the messages get resolved correctly.

Upvotes: 4

Related Questions