LoginSignup
17
17

More than 5 years have passed since last update.

Spring BootでカスタムValidatorにInjectionしたい時の設定

Posted at

以下のようにコンテナからInjectionされた値(Bean)を使ったカスタムValidatorがあったとする。

MyConstraintValidator.java
/**
 * コンテナで"hoge"に登録された文字列と一致するか検証する。
 */
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
    @Autowired
    private String hoge;
    @Override
    public void initialize(MyConstraint paramA) {
    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext paramConstraintValidatorContext) {
        Objects.requireNonNull(hoge);
        return Objects.equals(value, hoge);
    }
}

このValidatorにInjectionして使うには、Springのドキュメントでここらへんを見ると以下のような設定が必要になる。

<bean id="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

@Configurationなクラスで設定する場合はこうなる。

@Bean
public javax.validation.Validator localValidatorFactoryBean() {
   return new LocalValidatorFactoryBean();
}

コントローラでバリデーションする場合なんかには上記だけでも良いが、Hibernateで使う場合には以下の設定でEntityManagerFactoryにValidatorの参照を渡す必要がある。
http://stackoverflow.com/questions/2712345/jsr-303-dependency-injection-and-hibernate

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="jpaPropertyMap">
  <map>
   <entry key="javax.persistence.validation.factory" value-ref="validator" />               
  </map>
 </property>
</bean>

これをSpring Bootで設定する場合、SpringBootのドキュメントでここを見るとapplication.propertiesでspring.jpa.properties.*にJPAプロパティを指定すればいいのだがなんか嫌な予感。。。

application.properties
spring.jpa.properties.javax.persistence.validation.factory=validator

これでは"validator"という文字列を設定しているだけなのでエラーになってしまう。試しにクラス名を指定してみてもダメ。

Caused by: org.hibernate.cfg.beanvalidation.IntegrationException: Given object was not an instance of javax.validation.ValidatorFactory[java.lang.String]

Beanの参照を設定するにはプロパティファイルではだめぽなので@Configurationなクラスで設定するしかなさそう。

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, DataSource dataSource, JpaProperties jpaProperties) {

        LocalContainerEntityManagerFactoryBean factory = builder
                .dataSource(dataSource)
                .packages(Application.class)
                .persistenceUnit("default")
                .properties(jpaProperties.getHibernateProperties(dataSource))
                .build();

        Map<String, Object> jpaPropertyMap = new HashMap<>();
        jpaPropertyMap.put("javax.persistence.validation.factory", validator());
        factory.setJpaPropertyMap(jpaPropertyMap);
        return factory;
    }

LocalContainerEntityManagerFactoryBeanの生成部分はJpaBaseConfiguration.entityManagerFactory()のソースを参考にした。

やりたい事はjpaPropertyMap.put("javax.persistence.validation.factory", validator();の1行だけなんだけど、もっといいやり方はないんだろうか?

17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17