読者です 読者をやめる 読者になる 読者になる

かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot でメール送信する Web アプリケーションを作る ( その13 )( メール送信画面の作成7 )

概要

Spring Boot でメール送信する Web アプリケーションを作る ( その12 )( メール送信画面の作成6 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • メール送信画面の作成
    • 前回から引き続きテストクラスを書きます。web/mailsend/MailsendController のテストクラスです。

ソフトウェア一覧

参考にしたサイト

手順

Controller クラスのテストを作成する前にちょっと悩みました。。。

悩んだのは、Service クラスのテストでデータの保存やメール送信のテストを実施しましたが、Controller クラスのテストでもデータの保存、メール送信のテストまで実施した方がよいのか? という点です。

Controller クラスのテストでは最低でも入力チェックと画面遷移のテストはやるべきものだと思いますので、さすがにそれに加えてデータ保存やメール送信までテストするのはどう考えてもやりすぎですよね。。。 クラスをきちんと分けておけば、余程の理由がない限り Service クラスで実施したテストを Controller クラスのテストで重複して実施する必要性も感じません。

今回あまり深く考えずに Controller クラスと Service クラスに分けていたのですが、

  • テストの観点から考えると、Controller クラスと Service クラスはきちんと分けておいた方がテストし易いように思えました。
  • Controller クラスのテストは入力チェックと画面遷移をテストします。
  • Service クラスは入力チェックを通過した後のメインの処理 ( DB へのデータ保存等 ) をテストします。

という方針でいこうと思います。

web/mailsend/MailsendController のテストクラスの雛形の作成

  1. 以下の順序でテストクラスを作成します。

    1. Controller クラスからテストクラスを生成します。この時メソッドは1つもチェックしません。
    2. ネストしたクラスを利用して構造化しながらテストメソッドの定義だけを記述します。
    3. テストメソッドを実装します。
  2. src/main/java/ksbysample/webapp/email/web/mailsend の MailsendController.java から MailsendControllerTest.java を生成します。

  3. 構造化しながらテストメソッドの定義だけを記述します。src/test/java/ksbysample/webapp/email/web/mailsend の下の MailsendControllerTest.javaリンク先のその1の内容 に変更します。

MockMvcResource クラスの作成

  1. ksbysample-webapp-basic から以下のファイルをコピーしてファイル名を変更します。

    • src/test/java/ksbysample/webapp/basic/test/SecurityMockMvcResource.java
      → src/test/java/ksbysample/webapp/email/test/MockMvcResource.java
  2. src/test/java/ksbysample/webapp/email/test の下の MockMvcResource.javaリンク先の内容 に変更します。

初期表示のテストの作成

  1. src/test/java/ksbysample/webapp/email/web/mailsend の下の MailsendControllerTest.javaリンク先のその2の内容 に変更します。

  2. テストを実行します。ネストしたクラスのクラス名「初期表示のテスト」にカーソルを移動した後、コンテキストメニューを表示して「Run '初期表示のテスト' with Coverage」メニューを選択します。

    テストが全て成功することを確認します。

    f:id:ksby:20150523185643p:plain

入力チェックエラーのテストの作成

  1. ksbysample-webapp-basic から以下のファイルをコピーします。

    • src/test/java/ksbysample/webapp/basic/test/ErrorsResultMatchers.java
      → src/test/java/ksbysample/webapp/email/test/ErrorsResultMatchers.java
    • src/test/java/ksbysample/webapp/basic/test/TestHelper.java
      → src/test/java/ksbysample/webapp/email/test/TestHelper.java
  2. テストで使用する MailsendForm クラスのテストデータを作成します。src/test/resources/ksbysample/webapp/email/web/mailsend の下に mailsendForm_empty.yml, mailsendForm_max_patternerr.yml, mailsendForm_fv01.yml, mailsendForm_fv02.yml を新規作成します。作成後、リンク先の内容 に変更します。

  3. src/test/java/ksbysample/webapp/email/web/mailsend の下の MailsendControllerTest.javaリンク先のその3の内容 に変更します。

  4. テストを実行します。ネストしたクラスのクラス名「入力チェックエラーのテスト」にカーソルを移動した後、コンテキストメニューを表示して「Run '入力チェックエラーのテスト' with Coverage」メニューを選択します。

    「項目が資料請求_商品に関する苦情の場合に商品が何も選択されていない場合には入力チェックエラー」のテストが失敗しました。

    f:id:ksby:20150523220859p:plain

    原因は MailsendFormValidator クラスの validate メソッドif (mailsendForm.getItem() == null) { のところで mailsendForm.getItem() が null ではなく mailsendForm.getItem().size() == 0 の状態になっており、入力チェックエラーにならないためでした。

  5. src/main/java/ksbysample/webapp/email/web/mailsend の下の MailsendFormValidator.javaリンク先の内容 に変更します。

  6. 再度テストを実行します。今度はテストが全て成功します。

    f:id:ksby:20150523223131p:plain

正常処理時のテストの作成

  1. テストで使用する MailsendForm クラスのテストデータを作成します。src/test/resources/ksbysample/webapp/email/web/mailsend の下に mailsendForm_min.yml, mailsendForm_max.yml を新規作成します。作成後、リンク先の内容 に変更します。

  2. src/test/java/ksbysample/webapp/email/web/mailsend の下の MailsendControllerTest.javaリンク先のその4の内容 に変更します。

  3. テストを実行します。ネストしたクラスのクラス名「正常処理時のテスト」にカーソルを移動した後、コンテキストメニューを表示して「Run '正常処理時のテスト' with Coverage」メニューを選択します。

    「最小値で送信ボタンをクリックした場合」と「最大値で送信ボタンをクリックした場合」のテストが失敗しました。

    f:id:ksby:20150523235620p:plain

    原因は TestHelper クラスの postForm メソッドのバグでした。MailsendController クラスの send メソッドが呼び出された時点で mailsendForm.getItem() で取得したリストの値の前後に "[...]" という余計な括弧が付いていました。付かないように修正します。

  4. src/test/java/ksbysample/webapp/email/test の下の TestHelper.javaリンク先の内容 に変更します。

  5. 再度テストを実行します。今度はテストが全て成功します。

    f:id:ksby:20150524014104p:plain

全てのテストメソッドの実行、確認

  1. MailsendControllerTest の全てのテストを実行してみます。テストクラスのクラス名「MailsendControllerTest」にカーソルを移動した後、コンテキストメニューを表示して「Run 'MailsendControllerTest...' with Coverage」メニューを選択します。

    テストが全て成功することが確認できます。

    f:id:ksby:20150524014627p:plain

  2. これまで作成した全てのテストを実行してみます。Project View のルートでコンテキストメニューを表示して「Run 'Tests in 'ksbysample...' with Coverage」メニューを選択します。

    f:id:ksby:20150524015152p:plain

    こちらもテストが全て成功することが確認できます。

    f:id:ksby:20150524015539p:plain

commit、Push、Pull Request、マージ

  1. commit します。commit 時に Code Analysis のダイアログが表示されますが、TestHelper クラスの Javadoc の Warning と、build.gradle の Grgit 関連の Warning なので、今回は何も対応はせずに「Commit」ボタンをクリックします。

  2. GitHub へ Push、1.0.x-maketest-mailsend -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-maketest-mailsend ブランチを削除、をします。

最後に

最初の「Controller クラスのテストを作成する前にちょっと悩みました。。。」で Controller クラスのテストはどこまでやればよいのか? について考えたことを書きましたが、興味があってモックツール JMockit の調査をしていた時に下記のブログの記事で、

株式会社ジェニシス 技術開発事業部ブログ: 最強モックツール JMockit その4 内部newクラス

しかし、「二つのクラスが合体させてのテスト」というのは、厳密には「結合テスト」と言ってしまって良いでしょう。 単体テストフェーズであるユニットテストで行うのは、もちろん「単体テスト」です。

という記述を見かけました。この記述は自分にはすごく分かりやすくて、1つのテストで複数のクラスの機能をテストしないようにした方がよいのだなと理解できた次第です。どういうテストなのかということを考えることを忘れていましたね。。。

次回は。。。

まだ送信済メール検索機能には進みません。他のメール関連機能を実装したり、モックツール JMockit を試してみたりしたいので、以下の実装・調査を行います。

  • Thymeleaf による HTML メール送信機能を実装します。
  • 日本語のファイル名の添付ファイル付メールを送信する機能を実装します。
  • モックツール JMockit を試してみます。

ソースコード

MailsendControllerTest.java

■その1

package ksbysample.webapp.email.web.mailsend;

import ksbysample.webapp.email.Application;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(Enclosed.class)
public class MailsendControllerTest {

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 初期表示のテスト {

        @Test
        public void メール送信画面を表示する() throws Exception {
        }
        
    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 入力チェックエラーのテスト {

        @Test
        public void データ未入力時には入力チェックエラー() throws Exception {
            // NotBlank のテスト
        }

        @Test
        public void 最大文字数オーバー_パターンエラー時には入力チェックエラー() throws Exception {
            // Email/Size/Pattern のテスト
        }

        @Test
        public void 項目が資料請求_商品に関する苦情の場合に商品が何も選択されていない場合には入力チェックエラー() throws Exception {
        }

        @Test
        public void 項目がその他の場合に内容に何も入力されていない場合には入力チェックエラー() throws Exception {
        }
        
    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 正常処理時のテスト {

        @Test
        public void 最小値空ありで送信ボタンをクリックした場合() throws Exception {
        }

        @Test
        public void 最小値で送信ボタンをクリックした場合() throws Exception {
        }

        @Test
        public void 最大値で送信ボタンをクリックした場合() throws Exception {
        }
        
    }

}

■その2

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 初期表示のテスト {

        @Rule
        @Autowired
        public MockMvcResource mvc;
        
        @Test
        public void メール送信画面を表示する() throws Exception {
            // メール送信画面が表示されることを確認する
            mvc.nonauth.perform(get("/mailsend"))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("mailsend/mailsend"));
        }
        
    }

■その3

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 入力チェックエラーのテスト {

        private final MailsendForm mailsendFormEmpty
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_empty.yml"));
        private final MailsendForm mailsendFormMaxPatternerr
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_max_patternerr.yml"));
        private final MailsendForm mailsendFormFv01
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_fv01.yml"));
        private final MailsendForm mailsendFormFv02
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_fv02.yml"));

        @Rule
        @Autowired
        public MockMvcResource mvc;

        @Test
        public void データ未入力時には入力チェックエラー() throws Exception {
            // NotBlank のテスト
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormEmpty))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("mailsend/mailsend"))
                    .andExpect(model().hasErrors())
                    .andExpect(model().errorCount(3))
                    .andExpect(errors().hasFieldError("mailsendForm", "fromAddr", "NotBlank"))
                    .andExpect(errors().hasFieldError("mailsendForm", "toAddr", "NotBlank"))
                    .andExpect(errors().hasFieldError("mailsendForm", "subject", "NotBlank"));
        }

        @Test
        public void 最大文字数オーバー_パターンエラー時には入力チェックエラー() throws Exception {
            // Email/Size/Pattern のテスト
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormMaxPatternerr))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("mailsend/mailsend"))
                    .andExpect(model().hasErrors())
                    .andExpect(model().errorCount(7))
                    .andExpect(errors().hasFieldError("mailsendForm", "fromAddr", "Email"))
                    .andExpect(errors().hasFieldError("mailsendForm", "toAddr", "Email"))
                    .andExpect(errors().hasFieldError("mailsendForm", "subject", "Size"))
                    .andExpect(errors().hasFieldError("mailsendForm", "name", "Size"))
                    .andExpect(errors().hasFieldError("mailsendForm", "sex", "Pattern"))
                    .andExpect(errors().hasFieldError("mailsendForm", "type", "Pattern"))
                    .andExpect(errors().hasFieldError("mailsendForm", "naiyo", "Size"));
        }

        @Test
        public void 項目が資料請求_商品に関する苦情の場合に商品が何も選択されていない場合には入力チェックエラー() throws Exception {
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormFv01))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("mailsend/mailsend"))
                    .andExpect(model().hasErrors())
                    .andExpect(model().errorCount(1))
                    .andExpect(errors().hasGlobalError("mailsendForm", "mailsendForm.item.noSelect"));
        }

        @Test
        public void 項目がその他の場合に内容に何も入力されていない場合には入力チェックエラー() throws Exception {
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormFv02))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("text/html;charset=UTF-8"))
                    .andExpect(view().name("mailsend/mailsend"))
                    .andExpect(model().hasErrors())
                    .andExpect(model().errorCount(1))
                    .andExpect(errors().hasGlobalError("mailsendForm", "mailsendForm.naiyo.noText"));
        }
        
    }

■その4

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    public static class 正常処理時のテスト {

        private final MailsendForm mailsendFormMinimum
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_minimum.yml"));
        private final MailsendForm mailsendFormMin
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_min.yml"));
        private final MailsendForm mailsendFormMax
                = (MailsendForm) new Yaml().load(getClass().getResourceAsStream("mailsendForm_max.yml"));

        @Rule
        @Autowired
        public TestDataResource testDataResource;

        @Rule
        @Autowired
        public MailServerResource mailServer;

        @Rule
        @Autowired
        public MockMvcResource mvc;

        @Test
        public void 最小値空ありで送信ボタンをクリックした場合() throws Exception {
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormMinimum))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/mailsend"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(model().errorCount(0));
        }

        @Test
        public void 最小値で送信ボタンをクリックした場合() throws Exception {
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormMin))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/mailsend"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(model().errorCount(0));
        }

        @Test
        public void 最大値で送信ボタンをクリックした場合() throws Exception {
            mvc.nonauth.perform(TestHelper.postForm("/mailsend/send", this.mailsendFormMax))
                    .andExpect(status().isFound())
                    .andExpect(redirectedUrl("/mailsend"))
                    .andExpect(model().hasNoErrors())
                    .andExpect(model().errorCount(0));
        }
        
    }

MockMvcResource.java

package ksbysample.webapp.email.test;

import org.junit.rules.ExternalResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@Component
public class MockMvcResource extends ExternalResource {

    @Autowired
    private WebApplicationContext context;

    public MockMvc nonauth;

    @Override
    protected void before() throws Throwable {
        this.nonauth = MockMvcBuilders.webAppContextSetup(this.context)
                .build();
    }

}
  • 今回は Spring Security を使用していないので、フィールドを nonauth のみにし、Spring Security を利用していた部分を削除します。

mailsendForm_empty.yml, mailsendForm_max_patternerr.yml, mailsendForm_fv01.yml, mailsendForm_fv02.yml

■mailsendForm_empty.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: 
toAddr: 
subject: 
name: 
sex: 
type: 
item: 
naiyo: 

■mailsendForm_max_patternerr.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: a@
toAddr: b
subject: 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
name: 123456789012345678901234567890123
sex: 3
type: 4
item: 
naiyo: 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901

■mailsendForm_fv01.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: test@sample.com
toAddr: xxx@yyy.zzz
subject: テスト
name: 田中 太郎
sex: 1
type: 1
item: 
naiyo: これはテストです。

■mailsendForm_fv02.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: test@sample.com
toAddr: xxx@yyy.zzz
subject: テスト
name: 田中 太郎
sex: 1
type: 3
item:
  - 101
  - 102
  - 103
naiyo: 

MailsendFormValidator.java

    @Override
    public void validate(Object target, Errors errors) {
        MailsendForm mailsendForm = (MailsendForm)target;
        Constant constant = Constant.getInstance();

        // 「項目」が「資料請求」「商品に関する苦情」の場合には「商品」が何も選択されていない場合にはエラー
        if (StringUtils.equals(mailsendForm.getType(), "1")
                || StringUtils.equals(mailsendForm.getType(), "2")) {
            if ((mailsendForm.getItem() == null) || (mailsendForm.getItem().size() == 0)) {
                errors.reject("mailsendForm.item.noSelect");
            }
        }

        // 「項目」が「その他」の場合には「内容」に何も入力されていない場合にはエラー
        if (StringUtils.equals(mailsendForm.getType(), "3")) {
            if (mailsendForm.getNaiyo().length() == 0) {
                errors.reject("mailsendForm.naiyo.noText");
            }
        }
    }
  • if (mailsendForm.getItem() == null) {if ((mailsendForm.getItem() == null) || (mailsendForm.getItem().size() == 0)) { へ変更します。

mailsendForm_min.yml, mailsendForm_max.yml

■mailsendForm_min.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: a@a
toAddr: b@b
subject:name:sex: 1
type: 1
item: 
  - 101
naiyo:

■mailsendForm_max.yml

!!ksbysample.webapp.email.web.mailsend.MailsendForm
fromAddr: abcdeabcdeabcdeabcdeabcde@abcdeabcdeabcde.abcdeabcdeabcdeabcde.jp
toAddr: abcdeabcdeabcdeabcdeabcde@abcdeabcdeabcde.abcdeabcdeabcdeabcde.jp
subject: 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
name: 12345678901234567890123456789012
sex: 1
type: 2
item: 
  - 101
  - 102
  - 103
naiyo: 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

TestHelper.java

    public static MockHttpServletRequestBuilder postForm(String urlTemplate, Object form) throws IllegalAccessException {
        MockHttpServletRequestBuilder request = post(urlTemplate).contentType(MediaType.APPLICATION_FORM_URLENCODED);
        for (Field field : form.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.get(form) == null) {
                request = request.param(field.getName(), "");
            }
            else if (field.get(form) instanceof List<?>) {
                for (Object str : (List<?>)field.get(form)) {
                    request = request.param(field.getName(), str.toString());
                }
            }
            else {
                request = request.param(field.getName(), field.get(form).toString());
            }
        }
        return request;
    }
  • postForm メソッドの処理に else if (field.get(form) instanceof List<?>) { ... } の部分を追加します。

履歴

2015/05/24
初版発行。