JSR-303 アノテーション (クラスレベル) とバリデーターの実装を使用して、play 2.0.1 用のカスタムフォームバリデーターを作成しようとしました。
残念ながら、フォームを送信して検証に失敗すると、プレイのバグである可能性がある IllegalStateException が発生します (確認したいのですが)。
関連するコードの抜粋と問題の説明を以下に示します (わかりやすくするために、関連する部分のみを示します)。
コントローラーコードの一部 (フォーム送信の受信)
public static Result save() {
Form<UserForm> userForm = form(UserForm.class).bindFromRequest();
if (userForm.hasErrors()) {
return badRequest(createForm.render(userForm));
}
UserForm user = userForm.get();
バリデータは次のように宣言されます。
public class FieldMatchValidator extends Validator<Object>
implements ConstraintValidator<FieldMatch, Object>
検証アノテーションは次のように宣言されます。
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@play.data.Form.Display(name="constraint.fieldmatch")
public @interface FieldMatch {
String message() default FieldMatchValidator.message;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
フォームを送信するとエラーが発生します
Caused by: java.lang.IllegalStateException: No value
at play.libs.F$None.get(F.java:217) ~[play_2.9.1.jar:2.0.1]
at play.data.Form.get(Form.java:363) ~[play_2.9.1.jar:2.0.1]
at controllers.UsersController.save(UsersController.java:40) ~[classes/:2.0.1]
at Routes$$anonfun$routes$1$$anonfun$apply$25$$anonfun$apply$26.apply(routes_routing.scala:189) ~[classes/:na]
at Routes$$anonfun$routes$1$$anonfun$apply$25$$anonfun$apply$26.apply(routes_routing.scala:189) ~[classes/:na]
at play.core.Router$HandlerInvoker$$anon$4$$anon$1.invocation(Router.scala:1086) ~[play_2.9.1.jar:2.0.1]
上記の UsersController の行は、 UserForm user = userForm.get(); の呼び出しです。
問題がどこにあるかを理解しようとすると、問題のあるコードがおそらく Play の Form.java にあることがわかりました。
Form bind(Map data, String... allowedFields) には以下が含まれます。
if(result.hasErrors()) {
for(FieldError error: result.getFieldErrors()) {
...
}
return new Form(rootName, backedType, data, errors, None());
}
そして hasErrors() は
public boolean hasErrors() {
return !errors.isEmpty();
}
何が起こるかというと、result.hasErrors() は true を返しますが (クラス レベルで定義されたバリデータが失敗したため)、構築されたエラー リストは空のままです (result.getFieldErrors() は空のリストを返します)。
結果として、 Form.hasErrors() は false を返しますが、 Form.get() は失敗します。
何か足りないのですか、それとも実際にはバグですか?
よろしくお願いいたします。