JaValidとは
今回はJaValidを紹介したい。JaValidはJavaオブジェクトの状態を検証するためのオープンソースのバリデーションフレームワークである。JaValidを用いることで、Javaオブジェクトが取り得る状態の条件を設定して検証することができるようになる。
条件の設定にはアノテーションを利用する。たとえば@NotNullを指定されたオブジェクトに対してバリデーションを実行した場合、もしそのオブジェクトがNULLであったらエラーメッセージを出力する。条件をグループ化し、グループごとにバリデーションを実行できるような機能も提供される。
JaValidは単体で用いることもできるが、JSFやFacelets、Spring Framework、そして各種データベースとのインテグレーションもサポートしている。したがってこれらのフレームワークを利用している場合においても、自然な形でバリデーション機構を追加することができるようになっている。
なお、JaValidと同様にJavaオブジェクトのバリデーションを行うためのツールにはHibernate ValidatorやSpring Validationなどがある。またJSR 303ではJava SEやJava EEへの将来的な統合を目指してバリデーション用APIの標準化が進められている。JaValidの開発者であるMartijn Reuvers氏によると、JaValidでも将来のバージョンにおいてJSR 303をサポートする予定だいう。また他のツールとの比較については、すべてのツールにそれぞれ強味/弱味があるので、実際に試した上でそれぞれのニーズに合ったものを選択するのがいいと指摘している。
JaValidによるバリデーションの手順
JaValidはEclipse Public License v1.0に基づいて公開されており、このページよりバイナリ版とソースコード版のそれぞれをダウンロードできる。今回は最新版であるバージョン1.2のバイナリを入手して使用する。
JaValdの本体はdistディレクトリにあるjavalid-core-1.2.jarである。JaValidを使うためにはそれ以外にApache Log4J(http://logging.apache.org/log4j/)とJuel(http://juel.sourceforge.net/)が必要だが、それそれのバイナリもlibディレクトリに格納されているのでこれを利用すればよい。なお、dist以下にあるその他の3つのjarファイルは、それぞれJSF、Spring、データベースとのインテグレーションの際に必要となるものだ。
JaValidでバリデーション条件を設定する基本的な手順は、まず@ValidateDeinitionアノテーションを用いてクラス全体に対するバリデーションの設定を行い、そのクラスの各フィールドやメソッドに対してそれぞれアノテーションで条件を指定する。メソッドに対してアノテーションが指定された場合は、そのメソッドの戻り値がチェックの対象となる。バリデーション条件を指定するアノテーションには次のようなものがある。
**アノテーション** | **チェックされる内容** | **対象となるオブジェクト** |
---|---|---|
@NotNull | オブジェクトがNullでないか | |
@NotEmpty | オブジェクトが空でないか | 文字列、配列、Collection、Map |
@MinLength | 文字列の長さが指定された値以上であるか | 文字列 |
@MaxLength | 文字列の長さが指定された値以下であるか | 文字列 |
@ExactLength | 文字列の長さが指定された値と等しいか | 文字列 |
@BetweenLength | 文字列の長さが指定された値の範囲に収まるか | 文字列 |
@MinValue | 数値が指定された値以上であるか | 数値オブジェクト |
@MaxValue | 数値が指定された値以下であるか | 数値オブジェクト |
@LovConsistraint | 配列またはコレクションが指定された値を含むか | 配列、Collection |
@RegularExpression | 指定された正規表現にマッチするか | 文字列 |
@ValidateList | Listの要素であるクラスにバリデーション条件が指定されている場合、すべての要素がその条件を満たしているか | List |
@ValidateMap | Mapの要素であるクラスにバリデーション条件が指定されている場合、すべての要素がその条件を満たしているか | Map |
@CollectionSize | コレクションやMapのサイズ(要素数)が指定された条件を満たすか | Collection、Map |
@DateBefore | 日付が指定日よりも前か | Date |
@DateAfter | 日付が指定日よりも後か | Date |
@DateEqual | 日付が指定日であるかどうか | Date |
@DateNotEqual | 日付が指定日でないかどうか | Date |
各アノテーションにはそれぞれ指定すべきプロパティが用意されており、それを用いて条件を設定できるようになっている。たとえば@MinLengthの場合はlengthプロパティに長さを設定すればよい。また、各アノテーションごとに対象となるオブジェクトの種類が決められているので注意が必要。たとえば@xxxLength系のアノテーションはStringやStringBuffer、StringBuilderなどの文字列オブジェクトにしか指定することができない。
また上記とは別に「クラスレベルアノテーション」と呼ばれるアノテーションがある。これはクラスに対して指定することで、そのクラスの複数のフィールドやメソッドに対して同じ条件を設定することができる。クラスレベルアノテーションには次のようなものがある。対象となるフィールドおよびメソッドはvaluesプロパティで指定する。
**アノテーション** | **チェックされる内容** |
---|---|
@NotNullAll | 指定されたすべての値がNullでないか |
@NotEmptyAll | 指定されたすべての値が空でないか |
@NullOrNotNullAll | 指定され値がすべてNullか、またはすべてNullでないか |
@EmptyOrNotEmpty | 指定され値がすべて空か、またはすべて空でないか |
クラスのオブジェクトに対して実際にバリデーションを実行するには、まずAnnotationValidatorのインスタンスを生成し、validateObject()メソッドにそのオブジェクトを渡せばよい。このメソッドはバリデーションを実行した上でエラーメッセージを格納したValidationMessageのリストを返すので、これを調べればどの条件が満たされなかったのかを知ることができる。
バリデーションの実行例
それでは、実際に条件を設定したクラスを作成してバリデーションを実行してみよう。次のコードのUserクラスには、username、password、emailの3つのプロパティが定義されており、そのゲッターメソッドにそれぞれアノテーションを設定してある。このようにゲッターメソッドにアノテーションを指定することにより、各プロパティの値を検査することができるようになる。
リスト1の場合、usernameは空文字列(およびNull)以外、passwordはNull以外でかつ8文字以上、そしてemailはメールアドレスの形式でなければならない。
リスト1
package jp.co.mycom.toolde;
import org.javalid.annotations.core.ValidateDefinition;
import org.javalid.annotations.validation.MinLength;
import org.javalid.annotations.validation.NotEmpty;
import org.javalid.annotations.validation.NotNull;
import org.javalid.annotations.validation.RegularExpression;
@ValidateDefinition
public class User {
private String username;
private String password;
private String email;
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
@NotEmpty
public String getUsername() {
return username;
}
@NotNull
@MinLength(length=8)
public String getPassword() {
return password;
}
@RegularExpression(pattern="[\\w\\.\\-]+@(?:[\\w\\-]+\\.)+[\\w\\-]+")
public String getEmail() {
return this.email;
}
}
バリデーションを実施するコードはリスト2のようになる。
リスト2
package jp.co.mycom.toolde;
import java.util.Arrays;
import java.util.List;
import org.javalid.core.AnnotationValidator;
import org.javalid.core.AnnotationValidatorImpl;
import org.javalid.core.ValidationMessage;
public class UserTest {
public UserTest() {
AnnotationValidator validator = null;
List<ValidationMessage> messages = null;
User user = null;
// バリデーターの生成
validator = new AnnotationValidatorImpl();
// [1] エラー無し
user = new User("takaaki", "hogehoge", "takaaki@example.jp");
messages = validator.validateObject(user);
printErrorMessages(messages);
// [2] usernameとpasswordが不正
user = new User("", null, "takaaki@example.jp");
messages = validator.validateObject(user);
printErrorMessages(messages);
// [3] passwordが不正
user = new User("takaaki", "", "takaaki@example.jp");
messages = validator.validateObject(user);
printErrorMessages(messages);
// [4] emailが不正
user = new User("takaaki", "hogehoge", "takaaki.jp");
messages = validator.validateObject(user);
printErrorMessages(messages);
}
/*
* エラーメッセージの出力
*/
private void printErrorMessages(List<ValidationMessage> messages) {
if (messages.size() <= 0) {
System.out.println("No validation error.");
}
else {
for (ValidationMessage message: messages) {
System.out.println("Vallidation error from: " + message.getPath());
System.out.println(" Message: " + message.getMessage());
System.out.println(" Values: " + Arrays.toString(message.getValues()));
}
}
System.out.println("");
}
public static void main(String[] args) {
UserTest doit = new UserTest();
}
}
この例では、[1]は条件を満たしているが、[2]はusernameが空文字列かつpasswordがnullであり、[3]はpasswordが8文字未満、[4]はメールアドレス形式になっておらず、それぞれ条件を満たしていない。これを実行するとプロンプト1のように出力され、どの条件を満たしていないのかがわかる。
プロンプト1
No validation error.
Vallidation error from: username
Message: jv_error_valueIsEmpty
Values: []
Vallidation error from: password
Message: jv_error_valueIsNull
Values: null
Vallidation error from: password
Message: jv_error_valueIsNotMinLength
Values: [, 8]
Vallidation error from: email
Message: jv_error_valueNotMatchesRegPattern
Values: [takaaki.jp, [\w\.\-]+@(?:[\w\-]+\.)+[\w\-]+]
このようにJaValidの使い方そのものは非常にシンプルだ。基本的な利用においては特別な設定ファイルなどを必要とせず、手軽に適用できることが大きな利点と言える。