バリデーション
入力された値のチェックやデータベースに登録するカラムの値チェックを行います。
バリデーションの設定はチェックを行うフィールドの FeildDEF 注釈で行います。
/** 必須項目 */
@FieldDEF(validator=RequiredValidator.class)
private String userID;
バリデータがパラメータを要求する場合は FieldDEF#validatorParams
で指定します。複数のパラメータが必要な場合はカンマで区切ります。
/** 20バイトを超えるとエラー */
@FieldDEF(
validator = MaxByteLengthValidator.class,
validatorParams = "20, MS932"
)
private String userName;
複数のチェックを行う場合は配列で指定します。
この場合は validator と validatorParams を対応させなくてはなりません。
/** 必須チェックとバイト数チェックを行う */
@FieldDEF(
validator = { RequiredValidator.class, ByteLengthValidator.class },
validatorParams = { "", "8, MS932" }
)
private String zipCode;
FieldDEF#displayNameにフィールドの論理名をセットしておくと、
バリデーションエラーの際にメッセージにフィールド名ではなく論理名が表示されます。
また validatorMessage でメッセージを指定することができます。
@FieldDEF(
validator = { RequiredValidator.class, ByteLengthValidator.class },
validatorParams = { "", "6, MS932" },
validatorMessage = { "%1$sは必須項目です。", "%1$sは%3$s文字以内で入力してください。"},
displayName = "郵便番号",
)
private String zipCode;
メッセージは java.util.Formatter の書式でフォーマットされます。
フォーマットは第一引数に ValidatorResult#getDisplayName()で取得する名称、
第二引数に値オブジェクト、第三引数以降に FieldDEF#validatorParams
で指定したパラメータが順に渡されます。
上記例だと
「郵便番号は必須項目です。」「郵便番号は6文字以内で入力してください。」となります。
バリデーションの実行は
FieldValidator.validate(Object)
により行います。
このメソッドは妥当性チェックエラーがあった場合でも全てのフィールドのチェックを実行し、
エラーの時に作成したValidatorResultオブジェクトを格納したListを返します。
エラーがなかった場合は空のListになります。
// formBeanはチェック対象オブジェクト
List<ValidatorResult> results = FieldValidator.validate(formBean);
if (!results.isEmpty()) {
String message = "";
for (ValidatorResult result : results) {
message += result.getDisplayName() + " : " + result.getMessage() + "\n";
}
log.log(Level.WARNING, message);
return;
}
...
テーブルの1レコードを表現するエンティティクラスの場合は
新規に登録する場合は必須でも、更新の場合はそのカラムの必須チェックは不要です。
FieldValidator.validate(Object,boolean)
の第二引数にfalseを渡すと必須チェックを行いません。
ServiceActionのサブクラスではアクション呼出し時にバリデーションを行うように設定できます。
public class XXXAction extends ServiceAction {
@ContextParam // プリミティブ型、基本型の場合はvalidatorを指定
@FieldDEF (validator = RequiredValidator.class)
String requiredString;
@ContextParam // Beanオブジェクトはvalidationにtrueを指定
@FieldDEF (validation = true)
private XXXFormBean formBean;
public void execute() throws Exception {
...
}
}
// クライアントから渡されるパラメータを格納するクラス
public class XXXFormBean implements Srializable {
@FieldDEF(validator=RequiredValidator.class)
private String userID;
@FieldDEF(
validator = MaxByteLengthValidator.class,
validatorParams = "20, UTF-8"
)
private String name;
@FieldDEF(
validator = GenericFieldValidator.class,
validatorParams = "isEmail"
)
private String mail;
public String getUserID() { return userID; }
public String getName() { return name; }
public String getMail() { return mail; }
}
**** HTML ****
<form id="updateForm">
ユーザID <input type="text" id="userID"/><br/>
名前 <input type="text" id="name"/><br/>
メール <input type="text" id="mail"/><br/>
<input type="button" value="登録"
onclick="doForm('XXXAction',$('updateForm'),'next.html')"/>
</form>
バリデーションエラーがあった場合に処理を中止してクライアントにメッセージを表示します。
但し、レスポンダの指定でアクションの出力がテキストやバイナリデータの場合には
アラートを表示するJavaScriptを返すのは適切でないために何もレスポンスには返しません。
このケースで何らかのレスポンスを返すためにはアプリケーションで実装する必要があります。
@Responder(JpegImageResponder.class)
public class SearchImageAction extends ServiceAction {
@Override
public void doError(Exception e) throws Exception {
if (e instanceof ValidatorException) {
... // バリデーションエラー時の処理
} else {
super.doError(e);
}
}
}
エンティティから検索条件を抽出する
Persister#find(E)、Persister#update(E)、Persister#delete(E)
ではSQL実行前に主キーカラムの必須チェックを行います。
GenericPersisterでは
更新、登録時にエンティティオブジェクトのバリデーションを行います。
バリデーションの内容はエンティティクラスのフィールドに注釈されたFieldDEFの指定に従います。
但し必須チェックはUPDATEで更新対象のカラム値として扱われる場合についてはチェックを行いません。
値を設定しなかったカラムは
FieldDEF#acceptNull もしくは FieldDEF#acceptBlank で指定しない限り
更新されずに既存の値のままとなります。
必須チェックには
RequiredValidator
クラスを指定します。
下記のGenericFieldValidator
は、フィールドの値が null もしくは空文字列の場合はチェックを行いませんので
GenericValidator#isBlankOrNull(String)は使用できません。
Apatche Commons Validator の
GenericValidator
のラッパーです。
基本的なチェックはこれを使用します。
このバリデータの引数として
1番目に GenericValidator のメソッド名を
2番目以降にメソッドの2番目以降の引数を指定します。
メソッドの第一引数にこのフィールドの値が渡されます。
呼び出す GenericValidator のメソッドは
メソッド名が指定されたものと一致し、
かつ引数の数がパラメータの数と一致し、
かつ第一引数がフィールドの型と一致するものが選択されます。
// GenericValidator#isInRange(long,long,long) を実行する
@FieldDEF(
validator = GenericFieldValidator.class,
validatorParams = "isInRange, 100, 999"
)
private long number;
フィールドの値が null もしくは空の文字列の場合はチェックを行いませんので、
必須チェックが必要な場合は必ず
GenericFieldValidator
の
前に
RequiredValidator
を指定してください。
@FieldDEF(
validator = { RequiredValidator.class, GenericFieldValidator.class },
validatorParams = { "", "isLong"}
)
private String code;
文字数をバイトで数えるバイト・セマンティクスがデータベースのデフォルトであるケースが多いため、
文字セットによってバイト長が変わる日本語を含む文字長チェックは悩みの種です。
文字列のバイト長のチェックとして
ByteLengthValidator, MaxByteLengthValidator
を用意しています。
このチェックには文字セットを指定します。
// 文字セットを'MS932'で 12バイトを超えないことを検証
@FieldDEF (
validator = MaxByteLengthValidator.class,
validatorParams = "12, MS932"
)
private String name;
validatorParamsで文字セットが指定されていない場合、
WEB-INF/application-settings.xml
の 'database-charset'パラメータの値が使用されます。
バリデーションエラーの場合、ValidatorExceptionがスローされて
デフォルトではクライアントで警告メッセージを表示します。
システムによっては
メッセージエリアにメッセージを表示させたり、
フォーム要素のスタイルを変えてユーザに注意を促したりする場合が多いと思いますが、
このような場合は他の例外処理と同様にJavaScriptの関数
onActionError を用意しておくとこの動作をカスタマイズすることができます。
バリデーションエラー時に onActionErrorに渡されるオブジェクトは下記のようになります。
- REQUEST_URL 呼び出したアクションのURL
- REFERER アクションを呼び出した画面のURL
- アクションに渡したパラメータ
- ERROR 下記の内容を格納するオブジェクト
- className "ValidatorException"
- message 改行で連結した各ValidatorResultが出力するメッセージ
- validatorResults 以下の内容を格納するオブジェクトの配列
- validatorClassName バリデータクラス名
- message FieldDEF#validatorMessageから構築したメッセージ
vlidatorMessageの指定がなければバリデータのデフォルトメッセージ
- fieldName FieldDEF#displayNameで指定した名称、
もしくはデータベースカラム名、エンティティクラスのフィールド名
- value 入力された値
- params FieldDEF#validatorParamsで指定したバリデータパラメータの配列
エラーの要素を赤で表示するには下記のようにします。
入力がない場合には赤くはならないですが...
function onActionError(errorInfo) {
if (errorInfo.ERROR.className == "ValidatorException") {
var validatorResults = errorInfo.ERROR.validatorResults;
for (var i = 0; i < validatorResults; i++) {
var fieldName = validatorResults[i].fieldName;
Element.setStyle($(fieldName), { color : "red" });
}
} else {
...
}
}