--- title: 【Spring Advent Calendar 2013 6日目 Spring MVC + Bean Validationでフォームの未入力フィールドをnullにする spadc13 tags: [] categories: ["Programming", "Java", "Spring", "AdventCalendar", "2013"] date: 2013-12-05T15:48:43Z updated: 2013-12-05T15:48:43Z --- [Spring Advent Calendar][1] 6日目の記事です。 昨日も[僕][2]でしたね。 JJUG幹事会で[@cero_t][3]さんに聞かれたので、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][4]というのが用意されています。 適用の仕方は以下のように`@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`がついていないフィールドは必須チェックがなくなるので注意です。 明日も・・・おれか? [1]: http://www.adventar.org/calendars/153 [2]: /#/entries/207 [3]: https://twitter.com/cero_t [4]: http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/beans/propertyeditors/StringTrimmerEditor.html