82.参考: 妥当性チェックにHibernate Validatorを使う
概要
Spring Batchでは当初、妥当性チェックにSpring Modulesを使用するのを基本にしていました。
しかし、Spring Modulesは廃止になってしまいました。
では他の選択肢はというと、自作さえすればどのValidatorフレームワークも使えるかと思いますが面倒です。
ここでは、 Spring MVCにも使用され、世の中のスタンダードになっているHibernate Validatorを使用してみようと思います。
妥当性チェックの基本は他の記事に譲って、Hibernate Validatorの設定方法だけ見ていきます。
参考にするSpringのWEBページは、こちらです。
はじめに
すでにSpring MVCを使用したことがある人であればHibernate Validatorは使用したことがあるかと思います。
Spring MVCでは特に何も設定しなくても、デフォルトが Hibernate Validatorですので、Spring MVCを使用したことがある人でも
もしかしたら設定方法が分からないかも知れないですね。
ですが簡単です。Spring設定ファイルに用意されたクラスをDIするだけです。
簡単に見ていきましょう!
【基本の設定ファイルについて】
ここでは共通の設定ファイル(back-context.xml)などは他の記事に書いているものを使用します。
参考: 共通の設定
使用サンプル
<バッチ処理設定サンプル: /test/test-context.xml>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- SpringBatchの基盤部分に関する設定のインポート -->
<import resource="classpath:/test/back-context.xml" />
<!-- ジョブの設定 -->
<job id="job1" xmlns="http://www.springframework.org/schema/batch"
incrementer="jobParametersIncrementer">
<step id="step1" parent="simpleStep">
<tasklet>
<chunk reader="fileItemReader" processor="validatingItemProcessor" writer="fileItemWriter" />
</tasklet>
</step>
</job>
<!-- enables the functionality of JobOperator.startNextInstance(jobName) -->
<bean id="jobParametersIncrementer"
class="org.springframework.batch.core.launch.support.RunIdIncrementer" />
<bean id="simpleStep"
class="org.springframework.batch.core.step.item.SimpleStepFactoryBean"
abstract="true">
<property name="jobRepository" ref="jobRepository" />
<property name="commitInterval" value="1" />
</bean>
<bean id="fileItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="resource" value="classpath:/test/test.txt" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="num,name" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper" >
<property name="targetType" value="test.Member"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 列を入れ替えてファイルに出力するWriter -->
<bean id="fileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:c:/temp/test.txt" />
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="fieldExtractor">
<bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor" >
<property name="names" value="name,num" />
</bean>
</property>
</bean>
</property>
</bean>
<bean id="validatingItemProcessor" class="org.springframework.batch.item.validator.ValidatingItemProcessor">
<property name="validator">
<bean class="org.springframework.batch.item.validator.SpringValidator">
<property name="validator" ref="validator" />
</bean>
</property>
</bean>
<!--
Validatorを生成するファクトリー。
クラスパスにHibernateValidatorがあればそれを自動的に使用する。メッセージソースを設定することもできる。
-->
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
</beans>
Hibernate Validatorを使用するには、クラスパスにjarを置いて、上記のようにLocalValidatorFactoryBeanをDIするだけです、
このクラスは、自動的にクラスを読み込む作業と、妥当性チェックを実施する作業の2つを行います。
【注意点】
上記の設定で注意点は、LocalValidatorFactoryBeanが作成するValidatorは、org.springframework.validation.Validatorということです。
つまり、他の記事に書きましたがSpring BatchのValidatorは、バッチ用のパッケージになっていて、別のインターフェースです。
ですので、ItemProcessorに渡すときに、例のごとくSpringValidatorで変換しています。
<エラーメッセージ設定サンプル: /ValidationMessages_ja.properties>
javax.validation.constraints.AssertFalse.message=不正な値が入力されました。
javax.validation.constraints.AssertTrue.message=不正な値が入力されました。
javax.validation.constraints.DecimalMax.message={value}より同じか小さい値を入力してください。
javax.validation.constraints.DecimalMin.message={value}より同じか大きい値を入力してください。
javax.validation.constraints.Digits.message=整数{integer}桁以内、小数{fraction}桁以内で入力してください。
javax.validation.constraints.Future.message=未来の日付を入力してください。
javax.validation.constraints.Max.message={value}より同じか小さい値を入力してください。
javax.validation.constraints.Min.message={value}より同じか大きい値を入力してください。
javax.validation.constraints.NotNull.message=値が未入力です。
javax.validation.constraints.Null.message=値は未入力でなければいけません。
javax.validation.constraints.Past.message=過去の日付を入力してください。
javax.validation.constraints.Pattern.message="{regexp}"にマッチしていません。
javax.validation.constraints.Size.message=サイズは{min}から{max}の間の値を入力してください。
org.hibernate.validator.constraints.Email.message=E-mail形式で入力してください。
org.hibernate.validator.constraints.Length.message=文字の長さは{min}から{max}の間で入力してください。
org.hibernate.validator.constraints.NotEmpty.message=値が未入力です。
org.hibernate.validator.constraints.Range.message={min}から{max}の間の値を入力してください
こちらのWEBの内容から引用させていただきました。
⇒http://news.mynavi.jp/articles/2010/04/09/spring5/002.html
エラーメッセージ定義のサンプルです。
上記のファイル名にしておくと、自動で読み込まれます。
もし、違うファイル名にしたい場合はSpring設定ファイルで「ResourceBundleMessageSource」などのpropertiesファイル読み込みクラスを設定し、
「LocalValidatorFactoryBean」のvalidationMessageSourceプロパティーに設定する必要があるようです。
ちなみにこのエラーメッセージを設定しない場合はデフォルトの英語のメッセージが使用されます。
<POJOサンプル: /test/Member.java>
package test;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Range;
public class Member {
@NotNull
@Range(min=10, max=99)
private int num;
@NotNull
@Size(min=8)
private String name;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
読み込み用のPOJOです。
注目すべきは、赤字の部分で、アノテーションで妥当性チェック内容を設定しているところです。
参考: http://news.mynavi.jp/articles/2010/04/09/spring5/002.html
<読み込みファイルサンプル: /test/test.txt>
1,2
4,5
実際にItemReaderで読み込むファイルです。
値は何でも良いですが、わざとエラーが出るものを設定しています。
まとめ:実行時のログ等
上記を実行するとエラーが出ます。
そのエラーメッセージを見てみましょう。
【エラーログの例】
2014-08-03 12:05:12,059 ERROR [org.springframework.batch.core.step.AbstractStep] :: Encountered an error executing the step
org.springframework.batch.item.validator.ValidationException: Validation failed for test.Member@44343ad1:
Field error in object 'item' on field 'num': rejected value [1]; codes [Range.item.num,Range.num,Range.int,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.num,num]; arguments []; default message [num],99,10]; default message [10から99の間の値を入力してください]
Field error in object 'item' on field 'name': rejected value [2]; codes [Size.item.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.name,name]; arguments []; default message [name],2147483647,8]; default message [サイズは8から2147483647の間の値を入力してください。]
※見やすくするために空の行を追加していますが、実際は連続でログに出ます。
それほど難しくないですよね。
Created Date: 2014/08/03