intra-mart Accel Platform SAStruts+S2JDBC プログラミングガイド 第17版 2020-08-01

実装例:登録画面を作る

この項では、スマートフォンでTODOを登録する画面の実装例を紹介します。

前提条件

  • intra-mart Accel Platform をインストールし、初期設定までが完了していること。

  • ベースモジュールに SAStruts 開発フレームワーク、およびIM-Mobile Frameworkモジュールを含めて環境を作成してください。
    実行環境は単体テスト用で作成してください。

下準備 テーブル作成

以下手順を行う前に、以下のテーブルを作成してください。

  • mfw_sample

    列名 データ型 主キー NOT NULL 説明
    id VARCHAR(20) レコードのID
    user_cd VARCHAR(20)   登録ユーザID
    user_nm VARCHAR(20)   登録ユーザ名
    limit_date VARCHAR(20)     TODOの期限
    title VARCHAR(100)     TODOのタイトル
    comment VARCHAR(1000)     コメント
    progress NUMBER(3)     進捗度
    complete VARCHAR(1)     完了/未完了
    priority VARCHAR(1)     重要度
    timestmp VARCHAR(20)     タイムスタンプ
※その他のデータベースの場合は環境に合わせて調整してください。

画面を表示できるようにする

ソースの準備と配置

まず、以下2点のファイルを作成します。

  • sample.sastruts.action.samplesp.StoreAction

    package sample.sastruts.action.samplesp;
    
    import org.seasar.struts.annotation.Execute;
    
    public class StoreAction {
        /**
         * 登録ページのパスを返却します。
         * @return 入力ページのパス
         */
        @Execute(validator = false)
        public String index() {
            return "/sample/imsp/store/store.jsp";
        }
    }
    
  • %CONTEXT_PATH%/WEB-INF/view/sample/imsp/store/store.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
    <%@ taglib prefix="imsp" uri="http://www.intra-mart.co.jp/taglib/imsp" %>
    <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui" %>
    <imui:head>
      <title>TODO登録</title>
    </imui>
    <div data-role="page" id="main">
      <imsp:headerWithLink headerText="TODO登録" />
      <div class="ui-content" role="main">
      </div>
      <imsp:commonFooter dataPosition="fixed" />
    </div>
    

コラム

  • スマートフォン向けタグライブラリを使用するには以下のtaglibディレクティブを指定してください。
    <%@ taglib prefix="imsp" uri="http://www.intra-mart.co.jp/taglib/imsp" %>
  • <imsp:headerWithLink> - ヘッダ部左端に、任意のページに遷移のボタンを備えたヘッダを表示します。

  • <imsp:spCommonFooter> - フッタ部にHOMEボタンとログアウトボタンを表示します。

jqueyMobile1.4.5を読み込むようにする

ライブラリ群の設定を行います。本サンプルでは /samplesp 以下すべてに jQueryMobile1.4.5 が読み込まれるように設定します。

  • %CONTEXT_PATH%/WEB-INF/conf/theme-full-theme-path-config/im_mobile_sample.xml

    <theme-full-theme-path-config xmlns="http://www.intra-mart.jp/theme/theme-full-theme-path-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/theme/theme-full-theme-path-config theme-full-theme-path-config.xsd">
      <path client-type="sp" libraries-version="iap-8.0.11">/samplesp/.*</path>
    </theme-full-theme-path-config>
    

メニューの作成

メニューの設定を行います。

  • PCブラウザからテナント管理者でログインし、「メニュー設定」画面を表示します。

  • グローバルナビ(スマートフォン用)を選択し、新規メニューグループ「テストTODO」を作成します。

    ../../../../../_images/menugroup.PNG

新規メニューアイテムを作成します。

  • メニューアイテム名を「TODO登録」とし、URLを”samplesp/store”とします。

    ../../../../../_images/menuitem1.PNG

認可の設定

認可を設定します。

  • 「権限設定」ボタンを押下し権限設定(グローバルナビ(スマートフォン用))を表示します。

  • 「権限設定を開始する」ボタンを押下します。

  • テストTODOの権限の「参照」権限を認証済みユーザに付与します。

    ../../../../../_images/auth.PNG

    コラム

    • 認可の詳細については 認可 を参照してください。

画面を表示する

作成したページをメニューから表示します。

  • クライアントタイプをスマートフォン版へ切り替え、スマートフォン版グローバルナビを表示します。

  • メニューから「テストTODO」を選択すると、先ほど作成されたメニュー「TODO登録」が表示されます。

    スマホ版グローバルナビを表示
  • TODO登録を選択します。目的の画面を表示することができました。

    ../../../../../_images/blank1.PNG

コラム

この項目では、下記のポイントを確認しました。

  • スマートフォン用グローバルナビにメニューを表示するには、メニューカテゴリ「グローバルナビ(スマートフォン用)」に設定する

画面に要素を配置する

<div class=”ui-content” role=”main”>内に要素を配置します。
例としてテキストボックスとラベルを配置してみます。
ラベルを配置するには<imsp:fieldContain>タグを使用します。
  • store.jsp

    <imsp:fieldContain label="TODO名" required="true">
      <input type="text" name="title" />
    </imsp:fieldContain>
    
  • マークアップ結果。テーマにより最適化されたテキストボックスがされました。

    ../../../../../_images/text.PNG

同様に他の要素も配置していきます。

  • imsp:datePicker–日付文字列を参照入力するためのインタフェースを提供します。

    <imsp:fieldContain label="期限" required="true">
      <imsp:datePicker name="limit_date" />
    </imsp:fieldContain>
    
  • textarea–テキストエリアを提供します。

    <imsp:fieldContain label="コメント">
      <textarea name="comment"></textarea>
    </imsp:fieldContain>
    
  • imsp:controlGroup–フォーム要素をグループ化します。

  • imsp:radioButton–jQuery mobileで最適化されたラジオボタンを提供します。

    <imsp:controlGroup label="重要度">
      <imsp:radioButton name="priority" id="radio1" value="0" label="低" />
      <imsp:radioButton name="priority" id="radio2" value="1" label="中" />
      <imsp:radioButton name="priority" id="radio3" value="2" label="高" />
    </imsp:controlGroup>
    
  • imsp:slider–スライダーを提供します。

    <imsp:fieldContain label="進捗">
      <imsp:slider name="progress" min="<%=0 %>" max="<%=100 %>" />
    </imsp:fieldContain>
    
  • imsp:toggle–トグルスイッチを提供します。

    <imsp:fieldContain label="完了">
      <imsp:toggle name="complete" onLabel="完了" offLabel="未完了" onValue="1" offValue="0" />
    </imsp:fieldContain>
    
  • マークアップ結果。各要素が表示されました。

    画面要素配置結果

その他使用可能な要素についてはAPIリストを参照してください。

コラム

この項目では、下記のポイントを確認しました。

  • フォーム要素は<div class=”ui-content” role=”main”>内に配置する
  • ラベルを与える場合は<imsp:fieldContain>タグを使用する

登録処理を実装する

まず、フォームを受け取るためのFormクラスを作成します。

  • sample.sastruts.form.samplesp.StoreForm

    package sample.sastruts.form.samplesp;
    
    public class StoreForm {
        public String title;
        public String limit_date;
        public String comment;
        public String priority;
        public String progress;
        public String complete;
    }
    

次に登録処理用のエンティティクラスを作成します。

  • sample.sastruts.entity.MfwSample

    package sample.sastruts.entity;
    
    import java.math.BigDecimal;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="mfw_sample")
    public class MfwSample {
    
      @Column(name = "id")
      public String todoId;
    
      @Column(name = "user_cd")
      public String userCd;
    
      @Column(name = "user_nm")
      public String userName;
    
      public String title;
    
      @Column(name = "limit_date")
      public String limitDate;
    
      public String comment;
    
      public String priority;
    
      public BigDecimal progress;
    
      public String complete;
    
      public String timestmp;
    }
    

コラム

エンティティクラスの詳細については S2JDBC エンティティ を参照してください。

登録処理用のサービスクラスを定義します。
S2AbstractServiceクラスを継承し、型変数の宣言は上記で作成したエンティティを指定します。
  • sample.sastruts.service.samplesp.MfwSampleService

    package sample.sastruts.service.samplesp;
    
    import org.seasar.extension.jdbc.service.S2AbstractService;
    import sample.sastruts.entity.MfwSample;
    
    public class MfwSampleService extends S2AbstractService<MfwSample> {
    }
    

コラム

サービスクラスの詳細については S2JDBC サービスの作り方 を参照してください。

  • StoreActionクラスにフォームとサービスクラスのフィールド宣言を追加します。

    import javax.annotation.Resource;
    import org.seasar.struts.annotation.ActionForm;
    import sample.sastruts.form.samplesp.StoreForm;
    import sample.sastruts.service.samplesp.MfwSampleService;
    
    public class StoreAction {
    
        @Resource
        @ActionForm
        public StoreForm storeForm;
    
        @Resource
        public MfwSampleService mfwSampleService;
    
  • StoreActionクラスに登録処理メソッドを追加します。

    import java.io.IOException;
    import java.math.BigDecimal;
    
    import jp.co.intra_mart.foundation.context.Contexts;
    import jp.co.intra_mart.foundation.context.model.AccountContext;
    import jp.co.intra_mart.foundation.database.exception.DatabaseException;
    import jp.co.intra_mart.foundation.i18n.datetime.DateTime;
    import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatter;
    import jp.co.intra_mart.foundation.service.client.information.Identifier;
    import jp.co.intra_mart.foundation.user_context.model.UserContext;
    
    import sample.sastruts.entity.MfwSample;
    ...
    @Execute(validator = false)
    public String doStore() throws IOException, DatabaseException {
        //ユーザコンテキストを取得します。
        UserContext userProfile = Contexts.get(UserContext.class);
        //アカウントコンテキストからタイムゾーンを取得します。
        AccountContext accountContext = Contexts.get(AccountContext.class);
        DateTimeFormatter formatter = DateTimeFormatter.withPattern("yyyy/MM/dd HH:mm");
    
        //登録値の設定
        MfwSample insertData = new MfwSample();
        insertData.todoId = new Identifier().get();
        insertData.userCd = userProfile.getUserProfile().getUserCd();
        insertData.userName = userProfile.getUserProfile().getUserName();
        insertData.title = storeForm.title;
        insertData.limitDate = storeForm.limit_date;
        insertData.comment = storeForm.comment;
        insertData.priority =  storeForm.priority;
        insertData.complete =  storeForm.complete;
        if (storeForm.progress != null && !storeForm.progress.equals("")) {
            insertData.progress = new BigDecimal(storeForm.progress);
        }
        insertData.timestmp =  formatter.format(DateTime.now(accountContext.getTimeZone()));
    
        //登録処理実行
        int result = mfwSampleService.insert(insertData);
    
        return "/sample/imsp/store/store.jsp";
      }
    

コラム

  • 画面にFormタグと登録ボタンを配置します。 formタグのaction属性は先ほど追加したdoStoreメソッドとします。

        <form name="storeForm" name="storeForm" id="storeForm" method="POST" action="samplesp/store/doStore" data-ajax="false">
          <imsp:fieldContain label="TODO名" required="true">
            <input type="text" name="title" />
          </imsp:fieldContain>
          <imsp:fieldContain label="期限" required="true">
            ...
          <imsp:fieldContain label="完了">
            <imsp:toggle name="complete" onLabel="完了" offLabel="未完了" onValue="1" offValue="0" />
          </imsp:fieldContain>
            <a class="ui-btn ui-btn-b ui-corner-all" id="storeButton">登録</a>
        </form>
    

コラム

  • リンクにui-btnクラスを指定するとリンクをボタン表示します。
  • テーマを指定するにはクラス属性にui-btn-bのように「ui-btn-」の後にテーマを指定します。
  • ボタンを角丸にするにはui-corner-allクラスを指定します。
  • 「data-role=”button”」を指定してもボタンになりますが、jQuery Mobile1.4以降では非推奨となっています。
  • リンク、またはFORM要素にdata-ajax=”false”属性を付加することで明示的にAjax画面遷移をキャンセルすることができます。
  • 最後に登録ボタン押下時のイベントを実装します。
    このとき、記述箇所は<div data-role=”page”>内に実装することに
    気を付けてください。
    <div data-role="page" id="main">
    <script>
      (function($){
        $('#main').on("pagecreate", function() {
          $("#storeButton").tap(function() {
            $("#storeForm").submit();
          });
        });
      })(jQuery);
    </script>
    

注意

jQuery Mobileでは、Ajaxを使って画面遷移をする場合
遷移先画面の<div data-role=”page”>要素のみ取得し、表示中画面に挿入します。
そのため、<HEAD>タグ内にスクリプト、およびスタイルシートを宣言すると画面遷移時に読み込まれないため、不正動作をする場合があります。
  • サーバを再起動して画面を再表示します。 登録ボタン押下時、登録処理を経て画面が再表示されます。

コラム

この項目では、下記のポイントを確認しました。

  • フォームの入力内容を受け取るにはFormクラスを定義する
  • 任意のアクションに遷移するにはパスにアクション名を指定する

入力チェック処理を実装する(クライアントサイド)

store.jspにバリデーションルールを定義します。
rulesオブジェクトは入力チェックのルール、messagesオブジェクトは各ルールに対応したメッセージを定義します。
  • JSP

    <script>
      var rules = {
        "title": {
          required:true,
          maxlength:20
        },
        "limit_date": {
          required:true,
          date:true
        }
      };
      var messages = {
         "title": {
            required:"タイトルは必須です。",
            maxlength:"タイトルは20文字以内で入力してください"
         },
         "limit_date": {
           required:"期限は必須です。",
           maxlength:"期限は日付形式で入力してください"
         }
      };
    

登録ボタン押下時のスクリプト処理を修正します。

  • JSP

      (function($){
        $('#main').on("pagecreate", function() {
          //登録ボタン押下時のイベント
          $("#storeButton").tap(function() {
            //入力チェック実行
            if (imspValidate('#storeForm', rules, messages)) {
              //正常時
              imspAlert('入力エラーはありませんでした');
              $("#storeForm").submit();
            } else {
              imspAlert('入力エラーが発生しました', 'エラー');
            }
            return false;
          });
        });
      })(jQuery);
    </script>
    
  • マークアップ結果。タイトルと日付未入力の状態で登録ボタンを押下すると、
    エラーダイアログが表示され警告が出力されます。
入力チェックエラー

コラム

エラー仕様の詳細は、別ドキュメント クライアントサイド JavaScript の imspValidate を参照してください。

コラム

この項目では、下記のポイントを確認しました。

  • クライアントサイドで入力チェックを実装するにはバリデーションルールオブジェクトを定義する

非同期で登録処理を実行する

登録ボタン押下時のスクリプト処理を修正します。

  • store.jsp

     (function($){
       $('#main').on("pagecreate", function() {
         // Formの2度押し防止
         $('#storeForm').imspDisableOnSubmit();
         $("#storeButton").tap(function() {
           if (imspValidate('#storeForm', rules, messages)) {
              //Ajaxでのデータ送信
              imspAjaxSend('#storeForm', 'POST', 'json');
              //バリデーションのリセット
              imspResetForm('#storeForm');
           } else {
              imspAlert('入力エラーが発生しました', 'エラー');
           }
         });
       });
     })(jQuery);
    </script>
    

非同期で返却するレスポンスオブジェクトを定義します。

  • sample.sastruts.dto.samplesp.MyAjaxResponse

    package sample.sastruts.dto.samplesp;
    
    public class MyAjaxResponse {
        public String result;
        public boolean error;
        public String errorMessage;
        public String successMessage;
        public String[] detailMessages;
    }
    
  • doStoreメソッドを修正します。
    メソッドの返却値はnullとし、ResponseUtil.writeメソッドを使用し
    レスポンスオブジェクトのJSON形式に変換した文字列を返却します。
       import sample.sastruts.dto.samplesp.MyAjaxResponse;
       import net.arnx.jsonic.JSON;
       import org.seasar.struts.util.ResponseUtil;
       ...
       @Execute(validator = false)
       public String doStore() throws IOException, DatabaseException {
           //ユーザコンテキストを取得します。
           UserContext userProfile = Contexts.get(UserContext.class);
           ...
           insertData.timestmp =  formatter.format(DateTime.now(accountContext.getTimeZone()));
    
           MyAjaxResponse responseObject = new MyAjaxResponse();
           try {
               //登録処理実行
               int result = mfwSampleService.insert(insertData);
    
               //成功時
               responseObject.result = "success";
               responseObject.error = false;
               responseObject.successMessage = "登録が完了しました。";
            } catch (Exception e) {
               responseObject.error = true;
               responseObject.errorMessage = "データ登録時にエラーが発生しました。";
               responseObject.detailMessages = new String[] {"管理者にお問い合わせください。"};
            }
    
            //レスポンスオブジェクトをJSON文字列で返却
            ResponseUtil.write(JSON.encode(responseObject));
    
            return null;
       }
    
  • マークアップ結果。登録ボタン押下後にダイアログが表示され、
    登録処理が正常終了したことが確認できるようになりました。
    ../../../../../_images/ajax-success.PNG

コラム

この項目では、下記のポイントを確認しました。

  • クライアントから非同期でリクエストを送信するにはimspAjaxSend関数を使う

最終結果

  • sample.sastruts.action.samplesp.StoreAction.java

    package sample.sastruts.action.samplesp;
    
    import java.io.IOException;
    import java.math.BigDecimal;
    
    import javax.annotation.Resource;
    
    import jp.co.intra_mart.foundation.context.Contexts;
    import jp.co.intra_mart.foundation.context.model.AccountContext;
    import jp.co.intra_mart.foundation.database.exception.DatabaseException;
    import jp.co.intra_mart.foundation.i18n.datetime.DateTime;
    import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatter;
    import jp.co.intra_mart.foundation.service.client.information.Identifier;
    import jp.co.intra_mart.foundation.user_context.model.UserContext;
    import net.arnx.jsonic.JSON;
    
    import org.seasar.struts.annotation.ActionForm;
    import org.seasar.struts.annotation.Execute;
    import org.seasar.struts.util.ResponseUtil;
    
    import sample.sastruts.dto.samplesp.MyAjaxResponse;
    import sample.sastruts.entity.MfwSample;
    import sample.sastruts.form.samplesp.StoreForm;
    import sample.sastruts.service.samplesp.MfwSampleService;
    
    public class StoreAction {
        @Resource
        @ActionForm
        public StoreForm storeForm;
    
        @Resource
        public MfwSampleService mfwSampleService;
    
        @Execute(validator = false)
        public String doStore() throws IOException, DatabaseException {
            // ユーザコンテキストを取得します。
            final UserContext userProfile = Contexts.get(UserContext.class);
            // アカウントコンテキストからタイムゾーンを取得します。
            final AccountContext accountContext = Contexts.get(AccountContext.class);
            final DateTimeFormatter formatter = DateTimeFormatter.withPattern("yyyy/MM/dd HH:mm");
    
            // 登録値の設定
            final MfwSample insertData = new MfwSample();
            insertData.todoId = new Identifier().get();
            insertData.userCd = userProfile.getUserProfile().getUserCd();
            insertData.userName = userProfile.getUserProfile().getUserName();
            insertData.title = storeForm.title;
            insertData.limitDate = storeForm.limit_date;
            insertData.comment = storeForm.comment;
            insertData.priority = storeForm.priority;
            insertData.complete = storeForm.complete;
            if (storeForm.progress != null && !storeForm.progress.equals("")) {
                insertData.progress = new BigDecimal(storeForm.progress);
            }
            insertData.timestmp = formatter.format(DateTime.now(accountContext.getTimeZone()));
    
            final MyAjaxResponse responseObject = new MyAjaxResponse();
            try {
                // 登録処理実行
                final int result = mfwSampleService.insert(insertData);
    
                // 成功時
                responseObject.result = "success";
                responseObject.error = false;
                responseObject.successMessage = "登録が完了しました。";
            } catch (final Exception e) {
                e.printStackTrace();
                responseObject.error = true;
                responseObject.errorMessage = "データ登録時にエラーが発生しました。";
                responseObject.detailMessages = new String[] { "管理者にお問い合わせください。" };
            }
    
            // レスポンスオブジェクトをJSON文字列で返却
            ResponseUtil.write(JSON.encode(responseObject));
    
            return null;
        }
    
        /**
         * 登録ページのパスを返却します。
         * @return 入力ページのパス
         */
        @Execute(validator = false)
        public String index() {
            return "/sample/imsp/store/store.jsp";
        }
    }
    
  • %CONTEXT_PATH%/WEB-INF/view/sample/imsp/store/store.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
    <%@ taglib prefix="imsp" uri="http://www.intra-mart.co.jp/taglib/imsp" %>
    <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui" %>
    <imui:head>
    <title>TODO登録</title>
    </imui>
    <div data-role="page" id="main">
        <script>
            var rules = {
                "title": {
                    required:true,
                    maxlength:20
                },
                "limit_date": {
                    required:true,
                    date:true
                }
            };
            var messages = {
                "title": {
                    required:"タイトルは必須です。",
                    maxlength:"タイトルは20文字以内で入力してください"
                },
                "limit_date": {
                    required:"期限は必須です。",
                    maxlength:"期限は日付形式で入力してください"
                }
            };
        </script>
        <script>
            (function($){
                $('#main').on("pagecreate", function() {
                    // Formの2度押し防止
                    $('#storeForm').imspDisableOnSubmit();
                    $("#storeButton").tap(function() {
                        //入力チェック実行
                        if (imspValidate('#storeForm', rules, messages)) {
                            //Ajaxでのデータ送信
                            imspAjaxSend('#storeForm', 'POST', 'json');
                            //バリデーションのリセット
                            imspResetForm('#storeForm');
                        }
                    });
                });
            })(jQuery);
        </script>
        <imsp:headerWithLink headerText="TODO登録" />
        <div class="ui-content" role="main">
            <form name="storeForm" id="storeForm" method="POST" action="samplesp/store/doStore" data-ajax="false">
                <imsp:fieldContain label="TODO名" required="true">
                <input type="text" name="title" />
                </imsp:fieldContain>
    
                <imsp:fieldContain label="期限" required="true">
                <imsp:datePicker name="limit_date" />
                </imsp:fieldContain>
    
                <imsp:fieldContain label="コメント">
                <textarea name="comment"></textarea>
                </imsp:fieldContain>
    
                <imsp:controlGroup label="重要度">
                <imsp:radioButton name="priority" id="radio1" value="0" label="低" />
                <imsp:radioButton name="priority" id="radio2" value="1" label="中" />
                <imsp:radioButton name="priority" id="radio3" value="2" label="高" />
                </imsp:controlGroup>
    
                <imsp:fieldContain label="進捗">
                <imsp:slider name="progress" min="<%=0 %>" max="<%=100 %>" />
                </imsp:fieldContain>
    
                <imsp:fieldContain label="完了">
                <imsp:toggle name="complete" onLabel="完了" offLabel="未完了" onValue="1" offValue="0" />
                </imsp:fieldContain>
    
                <a data-role="button" data-theme="b" id="storeButton">登録</a>
            </form>
        </div>
        <imsp:commonFooter dataPosition="fixed" />
    </div>
    
  • sample.sastruts.form.samplesp.StoreForm.java

    package sample.sastruts.form.samplesp;
    
    public class StoreForm {
        public String title;
        public String limit_date;
        public String comment;
        public String priority;
        public String progress;
        public String complete;
    }
    
  • sample.sastruts.entity.MfwSample.java

    package sample.sastruts.entity;
    
    import java.math.BigDecimal;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "mfw_sample")
    public class MfwSample {
    
        @Column(name = "id")
        public String todoId;
    
        @Column(name = "user_cd")
        public String userCd;
    
        @Column(name = "user_nm")
        public String userName;
    
        public String title;
    
        @Column(name = "limit_date")
        public String limitDate;
    
        public String comment;
    
        public String priority;
    
        public BigDecimal progress;
    
        public String complete;
    
        public String timestmp;
    }
    
  • sample.sastruts.service.samplesp.MfwSampleService.java

    package sample.sastruts.service.samplesp;
    
    import org.seasar.extension.jdbc.service.S2AbstractService;
    import sample.sastruts.entity.MfwSample;
    
    public class MfwSampleService extends S2AbstractService<MfwSample> {
    }
    
  • sample.sastruts.dto.samplesp.MyAjaxResponse.java

    package sample.sastruts.dto.samplesp;
    
    public class MyAjaxResponse {
        public String result;
    
        public boolean error;
    
        public String errorMessage;
    
        public String successMessage;
    
        public String[] detailMessages;
    }