82.参考: 妥当性チェックにHibernate Validatorを使う

概要

Spring Batchでは当初、妥当性チェックにSpring Modulesを使用するのを基本にしていました。

しかし、Spring Modulesは廃止になってしまいました。

では他の選択肢はというと、自作さえすればどのValidatorフレームワークも使えるかと思いますが面倒です。

ここでは、 Spring MVCにも使用され、世の中のスタンダードになっているHibernate Validatorを使用してみようと思います。

妥当性チェックの基本は他の記事に譲って、Hibernate Validatorの設定方法だけ見ていきます。

参考にするSpringのWEBページは、こちらです。

参考: Spring3のValidation

はじめに

すでに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