Edited at

超簡単にJSPでenumを利用する方法


1. はじめに

Javaのenumは定数と異なりタイプセーフで、かつ、複数のデータを持つことが出来る便利なデータ型です。そのため、マスタなどのコードとその意味を一緒に定義することができます。

今回はJSPでそのenumを利用して、簡単にリストボックスやチェックボックスを表示する方法について説明したいと思います。

Webアプリはspring-boot(spring mvc、TERASOLUNA5.x)の前提とします。


2. enumの定義

今回のサンプルで利用するenumを定義します。intのcodeフィールドと表示するlabelフィールドのデータを持つenumとしました。

lombokを利用しない場合は明示的にコンストラクタとセッターも定義してください。


Status.java

package com.example.demo;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum Status {

APPROVAL(1, "承認"),
DENIAL(2, "否認"),
WITHDRAWAL(3, "取り下げ");

int code;
String label;

// ★ポイント1
public String getName() {
return name();
}
}


★ポイント1

enumはname()というメソッドを持っていますが、ゲッターとしてアクセスしたいため、ラップしたgetName()メソッドを定義します。

JSPでenumを利用するための対策です。


3. Formクラスの定義

入力されたデータを格納するFormクラスを定義します。


DemoForm.java

public class DemoForm implements Serializable {

// ★ポイント2
@NotNull
Status status;

// ommited
}


★ポイント2

定義したenumをそのままフィールドとして定義します。intのコードやStringのラベルで受け取る必要はありません。enumはデータ型なので、このフィールドは必ずStatusとなります。

必須項目としたいのでBean Validationの@NotNullアノテーションを付与しました。


4. enumでリストボックスを出力するJSP

今回の記事のポイントであるenumでリストボックスを出力するJSPを作成します。

JSPの標準機能とspringの機能(<form:xxx />はspringのタグ)を利用します。


enumでリストボックスを出力するJSP

<%-- ★ポイント3 --%>

<%@ page import="com.example.demo.Status" %>

... 省略 ...

<%-- ★ポイント4 --%>
<form:errors path="status"/>
<form:select path="status" items="${Status.values()}" itemLabel="label" itemValue="name" />


★ポイント3

JSPでStatusを参照したいため<%@ page import="fqcn" %>でクラスをインポートします。

JSPをスクリプトレットで記述していた時代はよく見かけましたが、最近はあまり見かけませんが、JSPの標準機能です。

★ポイント4

springの<form:select />タグを利用してリストボックスを出力します。属性が多いのでそれぞれについて以下で説明します。

属性
説明

path 
Formクラスの該当するフィールド名を指定します。今回はstatusになります。

items 
リストボックスに表示するデータを格納したコレクションや配列を指定します。
ここでenumのvalue()スタティックメソッドを呼び出すのがポイントです。このメソッドはenumの配列を返します。
これでenumの3項目を表示することができます。
★ポイント3でStatusをインポートしたのは、このスタティックメソッドを呼び出すためです。

itemLabel
リストボックスの表示項目に利用するフィールドを指定します。
今回はStatuslabelフィールドを表示したいのでlabelを指定します。

itemValue
リストボックスの値に利用するフィールドを指定します。
codeとしたくなりますが、ここにnameを指定するのがポイントです。

レンダリングする際はゲッターを呼び出すことになるので、★ポイント1で定義したgetName()メソッドが呼び出されることになります。


5. 出力されるリストボックスのHTML

出力されるリストボックスのHTMLを以下に示します。

<option>value属性にenumのname、表示項目にはlabelが設定されます。

valueStatusenumに定義されているnameと一致する値の場合、特別な処理を行うことなくFormクラスにバインドすることが可能になります。


出力されるHTML(見やすいように改行を追加)

<select id="status" name="status">

<option value="APPROVAL">承認</option>
<option value="DENIAL">否認</option>
<option value="WITHDRAWAL">取り下げ</option>
</select>

valueにenumに定義されていない値(ここではHOGE)を設定した場合、以下のようにTypeMismatchのエラーとなります。

HTMLのフォームを改ざんしてvalueに不正な値を設定した場合や、★ポイント4のitemValueで誤ってcodeフィールドを設定した場合などに発生します。


変換できない値を設定してHTTPリクエストした場合

Failed to convert property value of type java.lang.String to required type com.example.demo.Status for property status; 

nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String]
to type [com.example.demo.Status] for value HOGE; nested exception is java.lang.IllegalArgumentException: No enum constant com.example.demo.Status.HOGE

ここまでの説明で分かるようにJSPでもenumを利用することで、特別な入力チェックを用意することなく、Formに設定される時点でenumのタイプセーフが適用されます。


6. enumでチェックボックスを出力するJSP

Formクラスは複数選択できるように配列に変更します。


DemoForm.java

public class DemoForm implements Serializable {

@NotNull
@Size(min = 1, max = 3)
Status[] status;
// ommited
}


リストボックスを出力する際は<form:select />タグを利用しましたが、チェックボックスの場合は<form:checkboxes />タグを利用します。

チェックボックスを1つ出力する<form:checkbox />タグもあるので注意してください。


enumでチェックボックスを出力するJSP

<%-- ★ポイント5 --%>

<form:errors path="status"/>
<ul>
<form:checkboxes path="status" items="${Status.values()}"
itemLabel="label" itemValue="name" element="li" />
</ul>

★ポイント5

リストボックスと異なるelement属性について説明します。

これは出力するチェックボックスをラップするHTML要素を指定したい場合に設定します。

今回は<ul><li>を利用して一覧形式にしようと思いliを設定しました。


7. 出力されるチェックボックスのHTML

出力されるチェックボックスのHTMLを以下に示します。

チェックボックスのインプットフォームが<li>タグでラップされています。


出力されるHTML(見やすいように改行を追加)

<ul>

<li><input id="status1" name="status" type="checkbox" value="APPROVAL"/><label for="status1">承認</label></li>
<li><input id="status2" name="status" type="checkbox" value="DENIAL"/><label for="status2">否認</label></li>
<li><input id="status3" name="status" type="checkbox" value="WITHDRAWAL"/><label for="status3">取り下げ</label></li>
<input type="hidden" name="_status" value="on"/>
</ul>


8. さいごに

今回はJSPでそのenumを利用して、簡単にリストボックスやチェックボックスを表示する方法について説明しました。

今回の方法ではenumの定義を変更してもJSPもFormも修正する必要がありません。

enumを定義する際にgetName()メソッドを定義するという対策が必要ですが、特別な処理を実装することなく、フォームの入力値を簡単にenumにバインドすることができました。

ぜひJSPでもenumを利用してみてください。