前回のエントリで、Spring FrameworkにおいてString型のフォーム値が未入力の場合に、空文字ではなくnullを受け取る方法を説明しました。
この方法では、List
環境
方法
nullのリストを受け取るために、Springが提供しているCustomCollectionEditorというクラスを継承した自作クラスを作成します。 Kotlinでは引数の型の実装がすこし煩わしかったため、このクラスだけJavaで書いて、これをKotlinのクラスから利用するようにしました。
public class ListStringEditor extends CustomCollectionEditor { public ListStringEditor(Class<? extends Collection> collectionType) { super(collectionType); } public ListStringEditor(Class<? extends Collection> collectionType, boolean nullAsEmptyCollection) { super(collectionType, nullAsEmptyCollection); } @Override protected Object convertElement(Object element) { if (element instanceof String) { String str = (String) element; if (str.isBlank()) { return null; } } return element; } }
その後、実装した独自クラスをControllerクラス上でDataBinderにセットします。
@Controller class SampleController { // 省略 @InitBinder() fun allowEmptyDataBinding(binder: WebDataBinder) { binder.registerCustomEditor(List::class.java, ListStringEditor(List::class.java)) } // 省略 }
解説
Springが提供しているCustomCollectionEditorは、Collection型のプロパティに対するバインド処理を設定するためのPropertyEditorです。
CutomCollectionEditorの内部では、以下のように、setValue()
メソッドの中でCollection型の要素一つ一つに対してconvertElement()
メソッドを適用しています。
実際にconvertElement()
のJavaDocを読むと、overrideすることで任意の変換処理を実行できると書いてあるので、今回はこれを利用しました。
// 省略 public class CustomCollectionEditor extends PropertyEditorSupport { // 省略 @Override public void setValue(@Nullable Object value) { if (value == null && this.nullAsEmptyCollection) { super.setValue(createCollection(this.collectionType, 0)); } else if (value == null || (this.collectionType.isInstance(value) && !alwaysCreateNewCollection())) { // Use the source value as-is, as it matches the target type. super.setValue(value); } else if (value instanceof Collection) { // Convert Collection elements. Collection<?> source = (Collection<?>) value; Collection<Object> target = createCollection(this.collectionType, source.size()); for (Object elem : source) { target.add(convertElement(elem)); } super.setValue(target); } else if (value.getClass().isArray()) { // Convert array elements to Collection elements. int length = Array.getLength(value); Collection<Object> target = createCollection(this.collectionType, length); for (int i = 0; i < length; i++) { target.add(convertElement(Array.get(value, i))); } super.setValue(target); } else { // A plain value: convert it to a Collection with a single element. Collection<Object> target = createCollection(this.collectionType, 1); target.add(convertElement(value)); super.setValue(target); } } // 省略 protected Object convertElement(Object element) { return element; } // 省略 }
参考資料
CustomCollectionEditor (Spring Framework 5.2.7.RELEASE API)
spring-framework/CustomCollectionEditor.java at master · spring-projects/spring-framework · GitHub
This entry is released under version 2.0 of the Apache License.