IK.AM

@making's tech note


【Spring Advent Calendar 2013 6日目 Spring MVC + Bean Validationでフォームの未入力フィールドをnullにする spadc13

🗃 {Programming/Java/Spring/AdventCalendar/2013}
🗓 Updated at 2013-12-05T15:48:43Z  🗓 Created at 2013-12-05T15:48:43Z   🌎 English Page

Spring Advent Calendar 6日目の記事です。

昨日もでしたね。

JJUG幹事会で@cero_tさんに聞かれたので、Advent Calendarのネタとして答えておく。


Spring MVCでは文字列の入力フィールドに未入力の状態でフォームを送信した場合、 デフォルトでは、フォームオブジェクトのフィールドにnullではなく、空文字がバインドされます。(Integerフィールドだとnullがバインドされます)

以下のようなフォーム用JavaBeanを考えます。

public class HogeForm {
    @NotNull
    @Size(min = 1)
    private String username;
    //...
}

usernameフィールドを未入力で送信し、Bean ValidationでバインドされたHogeFormをチェックすると、usernameフィールドには空文字が入るので、@NotNullのエラーではなく、@Sizeによるエラーが発生します。

ちなみに@NotNull@Size(min=1)をまとめたのがHibernate Validatorで提供されている@NotEmpty(非標準)です。

通常は文字列フィールドの必須チェックは@NotNull+@Sizeまたは@NotEmptyでいいですが、これだと「未入力はOKだけど、入力されている場合は4文字以上で」というルールを表現できません。よくある要件だと思います。

この場合どうするかというと、一つの手段としては@EmptyOrGreaterThanみたいなアノテーションをつくるってのでもありですが、他の組み合わせパターンもでてくるとパターンごとにつくらないといけないのでちょっと面倒です。

もう一つのやり方として、Spring MVCのControllerの初期処理で空文字をnullにしてしまう、ということもできます。この処理のためにStringTrimmerEditorというのが用意されています。

適用の仕方は以下のように@InitBinderをつけたメソッドでStringTrimmerEditorを登録するだけです。

@Controller
@RequestMapping("hoge")
public class HogeController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

    // 略
}

Controller毎に設定すれば、設定したControllerにのみ上記の処理が適用されます。

Spring3.2から導入された@ControllerAdviceを使うと全Controllerに適用できます。これはプロジェクトで方針を決めて使用する必要があります。

@ControllerAdvice
public class HogeControllerAdvice {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

    // 略
}

‘StringTrimmerEditor‘の設定があれば、以下のアノテーションで「未入力はOKだけど、入力されている場合は4文字以上で」というルールを表現できます。

public class HogeForm {
    @Size(min = 4)
    private String username;
    //...
}

Bean Validationは基本nullは正常値なので、@NotNullがついていないフィールドは必須チェックがなくなるので注意です。

明日も・・・おれか?


✒️️ Edit  ⏰ History  🗑 Delete