質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

JSPで表示した明細部をActionFormのListにセットしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 8,846

chida3

score 15

前提・実現したいこと

自主勉強の一環で、SAStrutsによるWebアプリ開発をしています。

下記のようなことをやろうとしています。
①ActionFormにListを持たせて、その要素をJSPで一覧として表示。
②明細の各項目の値を変更してsubmit、ActionFormのListから値を取り出して処理。

発生している問題・エラーメッセージ

①まではできたのですが、
②において、ActionFormのListにアクセスしようとしたとき、NullPointerExceptionが発生します。
どのようにしたら、Listに明細をセットできるのでしょうか……。

該当のソースコード

■InputForm.java

public class InputForm {

    //明細部
    private List<Detail> detailList;

    public List<Detail> getDetailList() {
        return detailList;
    }
    public void setDetailList(List<Detail> detailList) {
        this.detailList = detailList;
    }
    public Detail getDetail(int index) {
        return getDetailList().get(index);
    }
    public void setDetail(Detail detail) {
        detailList.add(detail);
    }

    //明細行のDTO
    public class Detail {
        private int index;
        private String str;

        public int getIndex() {
            return index;
        }
        public void setIndex(int index) {
            this.index = index;
        }
        public String getStr() {
            return str;
        }
        public void setStr(String str) {
            this.str = str;
        }
    }

}


■InputAction.java

public class InputAction {

    @Resource
    @ActionForm
    protected InputForm inputForm;

    @Execute(validator=false)
    public String input() {
        List<Detail> detailList = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            Detail detail = inputForm.new Detail();
            detail.setIndex(i);
            detail.setStr("STR");
            detailList.add(detail);
        }
        inputForm.setDetailList(detailList);

        return "input.jsp";
    }

    @Execute(validator=false)
    public String exec() {
        //↓ここでNullPointerException
        inputForm.getDetailList().get(0);

        return "input.jsp";
    }
}


■input.jsp

<%@page pageEncoding="UTF-8"%>
<html>
<body>
    <s:form method="get">
    <s:submit property="exec" value="submit"/>
        <table>
            <tr>
                <td>No.</td>
                <td>str</td>
            </tr>
        <c:forEach var="detail" items="${inputForm.detailList}">
            <tr>
                <td>
                    <html:text name="detail" property="index" indexed="true"/>
                </td>
                <td>
                    <html:text name="detail" property="str" indexed="true"/>
                </td>
            </tr>
        </c:forEach>
        </table>
    </s:form>
</body>
</html>

参考にしたもの

下記サイトを一部参考にしたのですが、理解できなかったところもあり、反映し切れていません。どうぞご教示おねがいいたします。
http://www.civic-apps.com/2006/06/09/struts-using-list/
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=32607&forum=12

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

時間がかかってしまいましたが、解決しました。

修正後のソース

■InputForm.java

public class InputForm {
    public String classCd;
    public String categoryCd;
    public String segmentCd;
    public String seasonCd;

  //↓setter、getterは不要
    public List<Detail> detailList;
}

■input.jsp

<%@page pageEncoding="UTF-8"%>
<html>
<body>
    <s:form method="get">
    <s:submit property="exec" value="submit"/>
        <table>
            <tr>
                <td>No.</td>
                <td>str</td>
            </tr>

        <c:forEach var="detailList" items="${detailList}">
            <tr>
                <td>
                    <html:text name="detailList" property="index" indexed="true"/>
                </td>
                <td>
                    <html:text name="detailList" property="str" indexed="true"/>
                </td>
            </tr>
        </c:forEach>
        </table>
    </s:form>
</body>
</html>

上記に加え、明細部のDtoを作成しました。
■Detail.java

public class Detail {
    public int index;
    public String str;
}

※ActionFormの変更、Dtoの追加にともない、Actionでのインスタンス生成等の箇所を修正しています。

ポイント

フレームワークの動きについては、S2RequestProcessor.javaを読みました。
以下、括弧内の数字は、リンク先のソースの行数です。

1)Listのsetter、getterは不要
どうやらSAStrutsでは、フレームワークにおいて、リクエストパラメータをActionFormにセットする際、FormのメンバのListがnullだったらインスタンスを生成してくれるようです。(L580)
当初参考にしていたサイトは前身のStrutsを対象としたものだったので、同様に必要なのかと思っていましたが、違っていました。

2)jspでvarに指定する値をListの名前と合わせる
今回の場合は、「detailList」です。
var=detailListとすると、リクエストパラメータのkeyは「detailList[0]」のようになります。
フレームワークにて、ActionFormのプロパティに値をセットする際、セットすべきプロパティをリクエストパラメータのkeyの文字列で決めているようです。(L412-413)
修正前はdetailとしていたため、セットすべきプロパティが見つからず、NullPointerExceptionが発生していました。

3)内部クラスではなく、Dtoとして別クラスにするか、static修飾子をつける
1と2の修正をおこなったあと、以下のようなエラーが発生しました。

HTTPステータス 500 - [ESSR0059]クラス(hoge.form.InputForm)のプロパティ(detailList[2].index)の設定に失敗しました。理由はorg.seasar.framework.exception.InstantiationRuntimeException: [ESSR0041]hoge.form.InputForm$Detailの作成に失敗しました。理由はjava.lang.InstantiationException: hoge.form.InputForm$Detail

フレームワーク側で、Listの要素に持つクラスのインスタンス生成をおこなう箇所がありますが、Detailが内部クラスだったために、newInstanceでエラーが発生していたようです。(L585)

参考

↓まずこちらを見てなんとなくの対処法がわかりました。
リンク内容

↓フレームワークの内部動作については、ソースそのものを読んでようやく理解。
[sastruts]/trunk/sa-struts/src/main/java/org/seasar/struts/action/S2RequestProcessor.java
リンク内容

フレームワークのソース解析に関しては若干自信ないので、間違っていたらご指摘いただければ幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る