はじめてのBean Validation

Java EE 6のJavadocみていたら(NetBeansにはJava EEのドキュメントも付属している)javax.validationパッケージがあった。

そうだ、こいつもきていたんだった。

というわけでBean Validation (JSR-303)を触ってみる。

こいつはBeanに対する値のチェックをするライブラリである。

検査対象Bean

public class InputBean {
    @NotNull(message="なんかいれろ")
    String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}


バリデーションする側。今回はサーブレットでやってる。

@WebServlet(name="ValidateServlet", urlPatterns={"/ValidateServlet"})
public class ValidateServlet extends HttpServlet {
   
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        InputBean ib = new InputBean();
        ib.setData(request.getParameter("data"));
        
        ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
        Validator v = vf.getValidator();
        Set<ConstraintViolation<InputBean>> result = v.validate(ib);

        String message = "";
        for(ConstraintViolation<InputBean> cv : result){
            message += cv.getInvalidValue()+":"+cv.getMessage() + "<br>";
        }
        request.setAttribute("message", message);

        request.getRequestDispatcher("index.jsp").forward(request, response);
    } 

}

送信JSP

        ${message}
        <form action="ValidateServlet">
            <input type="text" name="data" value="${param.data}" >
            <input type="submit" value="そうしん">
        </form>

何も入力しないと「なんかいれろ」と表示されるかと思いきやそうではない。

あくまでも@NotNullはNullかどうかをチェックするためだ。リクエストパラメータ自体がある場合は長さ0の文字列がセットされるためである。

ためしに送信後にURLのパラメータ部分を削除して(GETなのですぐ消せる)サーブレットマッピングそのままでアクセスをすると「なんかいれろ」というバリデーションエラーメッセージが表示される。


では長さをチェックするアノテーションはあるのだろうか。
@Sizeというのがそれだ。

@Size(min=4,max=6,message="{min}から{max}文字の間のみおれが許す")
String data;

とやると4文字以上6文字以下というチェックが可能だ。ただし、nullの場合はチェックをしない。必須チェックをしたい場合は先ほどの@NotNullと合わせて@Size(min=1)と利用するとよいだろう。

メッセージについてだが、メッセージのパラメータに4と6の文字列がちゃんと挿入される。全体が「{}」で囲われている場合はメッセージリソースを参照するようだ。

数値の桁範囲チェック

@Digits(integer=4,fraction=1,message="整数{integer}桁、少数{fraction}桁までにしてくださいね♪")

Stringも使えるので便利かもしれない。
integer=9,fraction=0とやればIntegerの範囲内にマッピングできると覚えておくといいかも。

パターンマッチング

    @Pattern(regexp="1234.*" ,message="入力ミスだわさ")

flags指定もあってこれでUNIXライク改行とかそういうのも設定可能。

数値の範囲チェック

@Max(29,message="この年増が!")
@Min(20,message="この若造が!")
Integer data;

こいつはStringはダメ。数値系のみ。


文字列も対象にしたい場合は以下のようにする。

@DecimalMax("29",message="この年増が!")
@DecimalMin("20",message="この若造が!")
Integer data;

こちらは引数自体も文字列だけあって小数点設定も可能だ。BigDecimalシンタックスがないからこんなことになってる予感。


@Nullもしくは@NotNull以外は、nullの場合バリデーションをしないので注意しておこう。日時関係もあるが標準のは使い道がないので無視でいいと思う。自分で作ろう!