Reputation: 4385
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 Person
class:
@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
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
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