メッセージ管理 ================================================================================ .. only:: html .. contents:: 目次 :depth: 4 :local: Overview -------------------------------------------------------------------------------- | メッセージとは、画面や帳票等に表示する固定文言、またはユーザの画面操作の結果に応じて表示する動的文言を指す。 | また、エラーメッセージは、できるだけ細かく定義することを推奨する。 \ .. warning:: 以下の場合において、運用中、あるいは運用前の試験の際、エラーの原因を究明できなくなるリスクが生じる。(開発中は、特に困らないかもしれない。) * エラーメッセージを、1つのみ定義している * エラーメッセージを、「重要」と「警告」の2つしか定義していない その結果、開発メンバが少ない中で、メッセージの定義変更を行い、開発が進むにつれて、修正コストが増えることになる。 そのため、あらかじめメッセージは、細かい粒度で定義しておくことを推奨する。 メッセージタイプ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ユーザの画面操作の結果に応じて表示するメッセージは、内容に応じて、以下3種類のメッセージタイプに分けて管理する。 | メッセージを定義する際は、出力するメッセージが、どのタイプに属するか意識すること。 .. _message-level-table-label: .. tabularcolumns:: |p{0.20\linewidth}|p{0.20\linewidth}|p{0.60\linewidth}| .. list-table:: :header-rows: 1 :widths: 20 20 60 * - メッセージタイプ - カテゴリ - 概要 * - info - 情報メッセージ - ユーザの操作による処理が正常に実行された後、画面に表示するメッセージ。 * - warn - 警告メッセージ - 処理は継続できるが、注意喚起が必要な状態である場合に表示するメッセージ。(例:パスワード有効期限切れが近い場合の通知メッセージ) * - error - 入力エラーメッセージ - ユーザの入力値が不正な場合に、入力画面に表示するメッセージ。 * - - 業務エラーメッセージ - 業務ロジックでエラーと判定された場合に表示するメッセージ * - - システムエラーメッセージ - システム起因のエラー(データベースとの接続失敗等)が発生し、ユーザの操作でリカバリできない場合に表示するメッセージ | パターン別メッセージタイプの分類 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ メッセージの出力パターンを、以下に示す。 .. figure:: ./images/message-pattern.png :alt: message pattern :width: 95% メッセージパターンとメッセージの表示内容、及びメッセージタイプを、以下に示す。 .. tabularcolumns:: |p{0.05\linewidth}|p{0.15\linewidth}|p{0.20\linewidth}|p{0.10\linewidth}|p{0.50\linewidth}| .. list-table:: :header-rows: 1 :widths: 5 15 20 10 50 :class: longtable * - 記号 - パターン - 表示内容 - メッセージタイプ - 例 * - | (A) - | タイトル - | 画面のタイトル - | - - * 従業員登録画面 * - | - | ラベル - | 画面の項目名 | 帳票の項目名 | コメント | ガイダンス - | - - * ユーザー名 * パスワード * - | (B) - | ダイアログ - | 確認メッセージ - | info - * 登録してよろしいでしょうか? * 削除してよろしいでしょうか? * - | (C) - | 結果メッセージ - | 正常終了 - | info - * 登録しました。 * 削除しました。 * - | (D) - | - | 警告 - | warn - * パスワードの有効期限切れが間近です。パスワードを変更して下さい。 * サーバが混み合っています。時間をおいてから再度実行して下さい。 * - | (E) - | - | 単項目チェックエラー - | error - * "ユーザー名"は必須です。 * "名前"は20桁以内で入力してください。 * "金額"には数字を入力してください。 * - | (F) - | - | 相関チェックエラー - | error - * "パスワード"と"パスワード(確認用)"が一致しません。 * - | (G) - | - | 業務エラー - | error - * キャンセル可能期間を過ぎているため、予約を取り消せません。 * 登録可能件数を超えているため、登録できません。 * - | (H) - | - | システムエラー - | error - * XXXシステム閉塞中のため、しばらく経ってから再度実行して下さい * タイムアウトが発生しました。 * システムエラーが発生しました。 .. raw:: latex \newpage メッセージID体系 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | メッセージは、メッセージIDをつけて管理することを推奨する。 | 主な理由は、以下3つの利点を得るためである。 * メッセージ変更時に、ソースコードを修正することなくメッセージを変更するため * メッセージの出力箇所を特定しやすくするため * 国際化に対応できるため メッセージIDの決め方は、メンテナンス性向上のため、規約を作って統一することを強く推奨する。 | メッセージパターン毎のメッセージID規約例を以下に示す。 | 開発プロジェクトでメッセージID規約が定まっていない場合は、参考にされたい。 タイトル """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | 画面のタイトルに使用する、メッセージIDの決め方について説明する。 * フォーマット .. tabularcolumns:: |p{0.20\linewidth}|p{0.20\linewidth}|p{0.20\linewidth}|p{0.20\linewidth}|p{0.20\linewidth}| .. list-table:: :header-rows: 1 :widths: 20 20 20 20 20 * - 接頭句 - 区切り - 業務名 - 区切り - 画面名 * - | title - | . - | nnn* - | . - | nnn* * 記述内容 .. tabularcolumns:: |p{0.10\linewidth}|p{0.10\linewidth}|p{0.25\linewidth}|p{0.35\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 10 25 35 * - 項目 - 位置 - 内容 - 備考 * - | 接頭句 - | 1-5桁目 (5桁) - | "title" (固定) - | * - | 業務名 - | 可変長:任意 - | spring-mvc.xmlで定義したviewResolverのprefixの下のディレクトリ(JSPの上位ディレクトリ) - | * - | 画面名 - | 可変長:任意 - | JSP名 - | ファイル名が"aaa.jsp"の場合"aaa"の部分 * 定義例 .. code-block:: properties # "/WEB-INF/views/admin/top.jsp"の場合 title.admin.top=Admin Top # "/WEB-INF/views/staff/createForm.jsp"の場合 title.staff.createForm=Staff Register Input .. tip:: 本例は、Tilesを利用する場合に有効である。詳細は :doc:`../WebApplicationDetail/TilesLayout` を参照されたい。 Tilesを利用しない場合は、次に説明する\ :ref:`message-management_label-rule`\ の規約を利用しても良い。 | .. _message-management_label-rule: ラベル """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 画面のラベル、帳票の固定文言に使用する、メッセージIDの決め方について説明する。 * フォーマット .. tabularcolumns:: |p{0.13\linewidth}|p{0.13\linewidth}|p{0.16\linewidth}|p{0.13\linewidth}|p{0.13\linewidth}|p{0.13\linewidth}|p{0.13\linewidth}| .. list-table:: :header-rows: 1 :widths: 14 14 16 14 14 14 14 * - 接頭句 - 区切り - プロジェクト区分 - 区切り - 業務名 - 区切り - 項目名 * - | label - | . - | xx - | . - | nnn* - | . - | nnn* * 記述内容 .. tabularcolumns:: |p{0.10\linewidth}|p{0.10\linewidth}|p{0.25\linewidth}|p{0.35\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 10 25 35 * - 項目 - 位置 - 内容 - 備考 * - | 接頭句 - | 1-5桁目 (5桁) - | "label" (固定) - | * - | プロジェクト区分 - | 7-8桁名 (2桁) - | プロジェクト名のアルファベット2桁表記 - | * - | 業務名 - | 可変長:任意 - | - | * - | 項目名 - | 可変長:任意 - | ラベル名、説明文名 - | .. note:: 入力チェックエラーのメッセージに項目名(論理名)を含める場合は、 * フォームのモデル名 + "." + フィールド名 .. code-block:: properties staffForm.staffName = Staff name * フィールド名 .. code-block:: properties staffName = Staff name にする必要がある。 * 使用例 .. code-block:: properties # スタッフ登録画面のフォームの項目名 # プロジェクト区分=em (Event Management System) label.em.staff.staffName=Staff name # ツアー検索画面に表示する説明文の場合 # プロジェクト区分=tr (Tour Reservation System) label.tr.tourSearch.tourSearchMessage=You can search tours with the specified conditions. .. note:: プロジェクトが複数存在する場合に、メッセージIDが重複しないようにプロジェクト区分を定義する。 単一プロジェクトの場合でも、将来を見据えてプロジェクト区分を定義することを推奨する。 .. _message-management_result-rule: 結果メッセージ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 業務間で共通して使用するメッセージ '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 同一メッセージを定義しないように、複数の業務間で共有するメッセージについて説明する。 * フォーマット .. tabularcolumns:: |p{0.12\linewidth}|p{0.10\linewidth}|p{0.12\linewidth}|p{0.10\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}| .. list-table:: :header-rows: 1 :widths: 12 12 14 12 14 12 12 12 * - メッセージタイプ - 区切り - プロジェクト区分 - 区切り - 共通メッセージ区分 - 区切り - エラーレベル - 連番 * - | x - | . - | xx - | . - | fw - | . - | 9 - | 999 * 記述内容 .. tabularcolumns:: |p{0.20\linewidth}|p{0.20\linewidth}|p{0.40\linewidth}|p{0.10\linewidth}| .. list-table:: :header-rows: 1 :widths: 20 20 40 10 * - 項目 - 位置 - 内容 - 備考 * - | メッセージタイプ - | 1桁目 (1桁) - | info : i | warn : w | error : e - | * - | プロジェクト区分 - | 3-4桁目 (2桁) - | プロジェクト名のアルファベット2桁表記 - | * - | 共通メッセージ区分 - | 6-7桁目 (2桁) - | "fw" (固定) - | * - | エラーレベル - | 9桁 (1桁) - | 0-1 : 正常メッセージ | 2-4 : 業務エラー(準正常) | 5-7 : 入力チェックエラー | 8 : 業務エラー(エラー) | 9 : システムエラー - | * - | 連番 - | 10-12桁目 (3桁) - | 連番で利用する(000-999) - | メッセージ削除となっても連番は空き番として、削除しない * 使用例 .. code-block:: properties # 登録が成功した場合(正常メッセージ) i.ex.fw.0001=Registered successfully. # サーバリソース不足 w.ex.fw.9002=Server busy. Please, try again. # システムエラー発生の場合(システムエラー) e.ex.fw.9001=A system error has occurred. .. _message-properties-example: 各業務で個別に使用するメッセージ '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 業務で個別に使用するメッセージについて説明する。 * フォーマット .. tabularcolumns:: |p{0.12\linewidth}|p{0.10\linewidth}|p{0.12\linewidth}|p{0.10\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}|p{0.12\linewidth}| .. list-table:: :header-rows: 1 :widths: 12 12 14 12 14 12 12 12 * - メッセージタイプ - 区切り - プロジェクト区分 - 区切り - 業務メッセージ区分 - 区切り - エラーレベル - 連番 * - | x - | . - | xx - | . - | xx - | . - | 9 - | 999 * 記述内容 .. tabularcolumns:: |p{0.20\linewidth}|p{0.20\linewidth}|p{0.40\linewidth}|p{0.10\linewidth}| .. list-table:: :header-rows: 1 :widths: 20 20 40 10 * - 項目 - 位置 - 内容 - 備考 * - | メッセージタイプ - | 1桁目 (1桁) - | info : i | warn : w | error : e - | * - | プロジェクト区分 - | 3-4桁目 (2桁) - | プロジェクト名のアルファベット2桁表記 - | * - | 業務メッセージ区分 - | 6-7桁目 (2桁) - | 業務IDなど業務毎に決める2桁の文字 - | * - | エラーレベル - | 9桁 (1桁) - | 0-1 : 正常メッセージ | 2-4 : 業務エラー(準正常) | 5-7 : 入力チェックエラー | 8 : 業務エラー(エラー) | 9 : システムエラー - | * - | 連番 - | 10-12桁目 (3桁) - | 連番で利用する(000-999) - | メッセージ削除となっても連番は空き番として、削除しない * 使用例 .. code-block:: properties # ファイルのアップロードが成功した場合 i.ex.an.0001={0} upload completed. # パスワードの推奨変更期間が過ぎている場合 w.ex.an.2001=The recommended change interval of password has passed. Please change your password. # ファイルサイズが制限を超えている場合 e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. # データに不整合がある場合 e.ex.an.9001=There are inconsistencies in the data. | 入力チェックエラーメッセージ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 入力チェックでエラーがある場合に出力するメッセージについては、\ :ref:`Validation_message_def`\ を参照されたい。 .. note:: 入力チェックエラーの出力場所に関する基本方針を、以下に示す。 * | 単項目入力チェックエラーのメッセージは、対象の項目がわかるように項目の横に表示させる。 * | 相関入力チェックエラーのメッセージは、ページ上部などにまとめて表示させる。 * | 単項目チェックでもメッセージを項目の横に表示させにくい場合は、ページ上部に表示させる。 | その場合は、メッセージに項目名を含める。 | How to use -------------------------------------------------------------------------------- プロパティファイルに設定したメッセージの表示 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ プロパティを使用する際の設定 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" メッセージ管理を行う\ ``org.springframework.context.MessageSource``\ の実装クラスの定義を行う。 * applicationContext.xml .. code-block:: xml i18n/application-messages .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | ``MessageSource``\ の定義。ここでは\ ``ResourceBundleMessageSource``\ を使用する。 * - | (2) - | 使用するメッセージプロパティの基底名を定義する。クラスパス相対で指定する。 | この例では"src/main/resources/i18n/application-messages.properties"を読み込む。 .. _properties-display: プロパティに設定したメッセージの表示 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" * application-messages.properties ここでは、\ :file:`application-messages.properties`\ にメッセージを定義する例を示す。 .. code-block:: properties label.aa.bb.year=Year label.aa.bb.month=Month label.aa.bb.day=Day .. note:: 文字コード「ISO-8859-1」では表現できない文字(日本語など)は\ ``native2ascii``\ コマンドで ISO-8859-1に変換して使用することが多かった。しかし、JDK 6からは文字コードを指定できるようになったため、 変換する必要はない。文字コードUTF-8にすることで、propertiesファイルに直接日本語等を使用できる。 * application-messages.properties .. code-block:: properties label.aa.bb.year=年 label.aa.bb.month=月 label.aa.bb.day=日 この場合、以下のように、\ ``ResourceBundleMessageSource``\ にも読み込む文字コードを指定する必要がある。 * applicationContext.xml .. code-block:: java :emphasize-lines: 8 i18n/application-messages デフォルトではISO-8859-1が使用されるため、日本語等をpropertiesファイルに直接記述したい場合は、 必ず\ ``defaultEncoding``\ を設定すること。 * JSP 上記で設定したメッセージをJSPからは、\ ````\ タグを用いて表示できる。 \ :ref:`view_jsp_include-label`\ の設定が必要である。 .. code-block:: jsp フォームのラベルと使用する場合は、以下のように使用すれば良い。 .. code-block:: jsp :emphasize-lines: 3,7,11 :
:
:
ブラウザで表示すると以下のように出力される。 .. figure:: ./images_MessageManagement/message-management-ymd.png :width: 40% .. tip:: 国際化に対応する場合は、 .. code-block:: text src/main/resources/i18n ├ application-messages.properties (英語メッセージ) ├ application-messages_fr.properties (フランス語メッセージ) ├ ... └ application-messages_ja.properties (日本語メッセージ) というように各言語用のpropertiesファイルを作成すればよい。 詳細は、\ :doc:`../WebApplicationDetail/Internationalization`\ を参照されたい。 .. _message-display: 結果メッセージの表示 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | サーバサイドでの処理の成功や、失敗を示す結果メッセージを格納するクラスとして、 | 共通ライブラリでは、\ ``org.terasoluna.gfw.common.message.ResultMessages``\ 、および\ ``org.terasoluna.gfw.common.message.ResultMessage``\ を提供している。 .. tabularcolumns:: |p{0.20\linewidth}|p{0.80\linewidth}| .. list-table:: :header-rows: 1 :widths: 20 80 * - クラス名 - 説明 * - | ``ResultMessages`` - | 結果メッセージの一覧とメッセージタイプを持つクラス。 | 結果メッセージの一覧は\ ``List``\ 、メッセージタイプは\ ``org.terasoluna.gfw.common.message.ResultMessageType``\ インタフェースで表現される。 * - | ``ResultMessage`` - | 結果メッセージのメッセージID、または、メッセージ本文を持つクラス。 | この結果メッセージをJSPで表示するためのJSPタグライブラリとして、\ ````\ タグも提供される。 基本的な結果メッセージの使用方法 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Controllerで\ ``ResultMessages``\ を生成して画面に渡し、JSPで\ ````\ タグを使用して、 結果メッセージを表示する方法を説明する。 * Controllerクラス ``ResultMessages``\ オブジェクトの生成方法、および画面へメッセージを渡す方法を示す。 application-messages.proertiesには、\ :ref:`message-properties-example`\ の例が定義されていることとする。 .. code-block:: java package com.example.sample.app.message; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.terasoluna.gfw.common.message.ResultMessages; @Controller @RequestMapping("message") public class MessageController { @RequestMapping(method = RequestMethod.GET) public String hello(Model model) { ResultMessages messages = ResultMessages.error().add("e.ex.an.9001"); // (1) model.addAttribute(messages); // (2) return "message/index"; } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | メッセージタイプが"error"である\ ``ResultMessages``\ を作成し、 | メッセージIDが"e.ex.an.9001"である結果メッセージを設定する。 | この処理は次と同義である。 | ``ResultMessages.error().add(ResultMessage.fromCode("e.ex.an.9001"));`` | メッセージIDを指定する場合は、\ ``ResultMessage``\ オブジェクトの生成を省略できるため、省略することを推奨する。 * - | (2) - | \ ``ResultMessages``\ をModelに追加する。 | 属性は指定しなくてよい。(属性名は"resultMessages"になる) * JSP WEB-INF/views/message/index.jspを、以下のように記述する。 .. code-block:: jsp Result Message Example

Result Message

.. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | ```` タグをデフォルト設定で使用する。 | デフォルトでは、属性名が"resultMessages"のオブジェクトを表示する。 | そのため、デフォルトではControllerからModelに\ ``ResultMessages``\ を設定する際に、属性名を設定する必要がない。 ブラウザで表示すると、以下のように出力される。 .. figure:: ./images_MessageManagement/message-management-resultmessage-basic.png :width: 40% \ ```` によって出力されるHTMLを、以下に示す(説明しやすくするために整形している)。 .. code-block:: html
  • There are inconsistencies in the data.
.. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | メッセージタイプに対応して"alert-error"クラスが付与されている。デフォルトでは\ ``
``\ タグのclassに"error error-[メッセージタイプ]"が付与される。 * - | (2) - | 結果メッセージのリストが\ ``
    ``\ タグで出力される。 * - | (3) - | メッセージIDに対応するメッセージが\ ``MessageSource``\ から解決される。 ````\ はclassを付けたHTMLを出力するだけであるため、見栄えは出力されたclassに合わせてCSSでカスタマイズする必要がある(後述する)。 .. note:: \ ``ResultMessages.error().add(ResultMessage.fromText("There are inconsistencies in the data."));``\ というように、 メッセージの本文をハードコードすることもできるが、保守性を高めるため、メッセージキーを使用して\ ``ResultMessage``\ オブジェクトを作成し、 メッセージ本文はプロパティファイルから取得することを推奨する。 | メッセージのプレースホルダに値を埋める場合は、次のように\ ``add``\ メソッドの第二引数以降に設定すればよい。 .. code-block:: java ResultMessages messages = ResultMessages.error().add("e.ex.an.8001", 1024); model.addAttribute(messages); この場合、\ ````\ タグにより、以下のようなHTMLが出力される。 .. code-block:: html
    • Cannot upload, Because the file size must be less than 1,024MB.
    \ .. warning:: **terasoluna-gfw-web 1.0.0.RELEASEを使用してプレースホルダに値を埋める場合の注意点** terasoluna-gfw-web 1.0.0.RELEASEを使用している場合、\ **プレースホルダにユーザの入力値を埋め込むとXSS脆弱性の危険がある。**\ ユーザの入力値にXSS対策が必要な文字が含まれる可能性がある場合は、プレースホルダに値を埋め込まないようにすること。 terasoluna-gfw-web 1.0.1.RELEASE以上を使用している場合は、ユーザの入力値をプレースホルダに埋め込んでもXSS脆弱性は発生しない。 .. note:: \ ``ResourceBundleMessageSource``\ はメッセージを生成する際に\ ``java.text.MessageFormat``\ を使用するため、\ ``1024``\ は カンマ区切りで\ ``1,024``\ と表示される。カンマが不要な場合は、プロパティファイルには以下のように設定する。 .. code-block:: properties e.ex.an.8001=Cannot upload, Because the file size must be less than {0,number,#}MB. 詳細は、\ `Javadoc `_\ を参照されたい。 | 以下のように、複数の結果メッセージを設定することもできる。 .. code-block:: java ResultMessages messages = ResultMessages.error() .add("e.ex.an.9001") .add("e.ex.an.8001", 1024); model.addAttribute(messages); この場合は、次のようなHTMLが出力される(JSPの変更は、不要である)。 .. code-block:: html
    • There are inconsistencies in the data.
    • Cannot upload, Because the file size must be less than 1,024MB.
    infoメッセージを表示したい場合は、次のように\ ``ResultMessages.info()``\ メソッドで\ ``ResultMessages``\ オブジェクトを作成すればよい。 .. code-block:: java ResultMessages messages = ResultMessages.info().add("i.ex.an.0001", "XXXX"); model.addAttribute(messages); 以下のようなHTMLが、出力される。 .. code-block:: html
    • XXXX upload completed.
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | メッセージタイプに対応して、出力されるclass名が"alert alert-**info**"に変わっている。 標準では、以下のメッセージタイプが用意されている。 .. tabularcolumns:: |p{0.15\linewidth}|p{0.30\linewidth}|p{0.25\linewidth}|p{0.30\linewidth}| .. list-table:: :header-rows: 1 :widths: 15 30 25 30 * - メッセージタイプ - \ ``ResultMessages``\ オブジェクトの作成 - デフォルトで出力されるclass名 - 備考 * - | success - | ``ResultMessages.success()``\ - | alert alert-success - | \- * - | info - | \ ``ResultMessages.info()``\ - | alert alert-info - | \- * - | warn - | \ ``ResultMessages.warn()``\ - | alert alert-warn - | メッセージタイプ「warning」の追加に伴い、terasoluna-gfw-common 5.0.0.RELEASEから非推奨。 | \ **このメッセージタイプは将来削除される可能性がある。**\ * - | warning - | \ ``ResultMessages.warning()``\ - | alert alert-warning - | CSSフレームワークである\ `Bootstrap `_ の\ `Alertsコンポーネント `_\ で用意されているメッセージタイプをデフォルトでサポートするために、terasoluna-gfw-common 5.0.0.RELEASEから追加。 * - | error - | \ ``ResultMessages.error()``\ - | alert alert-error - | \- * - | danger - | \ ``ResultMessages.danger()``\ - | alert alert-danger - | \- メッセージタイプに応じてCSSを定義されたい。以下に、CSSを適用した場合の例を示す。 .. code-block:: css .alert { margin-bottom: 15px; padding: 10px; border: 1px solid; border-radius: 4px; text-shadow: 0 1px 0 #ffffff; } .alert-info { background: #ebf7fd; color: #2d7091; border-color: rgba(45, 112, 145, 0.3); } .alert-warning { background: #fffceb; color: #e28327; border-color: rgba(226, 131, 39, 0.3); } .alert-error { background: #fff1f0; color: #d85030; border-color: rgba(216, 80, 48, 0.3); } * \ ``ResultMessages.error().add("e.ex.an.9001")``\ を\ ````\ で出力した例 .. figure:: ./images_MessageManagement/message-management-resultmessage-error.jpg :width: 100% * \ ``ResultMessages.warning().add("w.ex.an.2001")``\ を\ ````\ で出力した例 .. figure:: ./images_MessageManagement/message-management-resultmessage-warn.jpg :width: 100% * \ ``ResultMessages.info().add("i.ex.an.0001", "XXXX")``\ を\ ````\ で出力した例 .. figure:: ./images_MessageManagement/message-management-resultmessage-info.jpg :width: 100% .. note:: successとdangerは、スタイルに多様性を持たせるために用意されている。本ガイドラインでは、successとinfo、errorとdangerは同義である。 .. tip:: CSSフレームワークである\ `Bootstrap `_ の\ `Alertsコンポーネント `_\ は、\ ````\ のデフォルト設定で利用できる。 .. warning:: 本例では、メッセージキーをハードコードで設定している。しかしながら、保守性を高めるためにも、メッセージキーは、定数クラスにまとめることを推奨する。 :ref:`message-management-messagekeysgen`\ を参照されたい。 結果メッセージの属性名指定 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | \ ``ResultMessages``\ をModelに追加する場合、基本的には属性名を省略できる。 | ただし、\ ``ResultMessages``\ は一つのメッセージタイプしか表現できない。 | 1画面に異なるメッセージタイプの\ ``ResultMessages``\ を\ **同時に**\ 表示したい場合は、明示的に属性名を指定してModelに設定する必要がある。 * Controller (MessageControllerに追加) .. code-block:: java @RequestMapping(value = "showMessages", method = RequestMethod.GET) public String showMessages(Model model) { model.addAttribute("messages1", ResultMessages.warning().add("w.ex.an.2001")); // (1) model.addAttribute("messages2", ResultMessages.error().add("e.ex.an.9001")); // (2) return "message/showMessages"; } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | メッセージタイプが"warning"である、\ ``ResultMessages``\ を属性名"messages1"でModelに追加する。 * - | (2) - | メッセージタイプが"info"である、\ ``ResultMessages``\ を属性名"messages2"でModelに追加する。 * JSP (WEB-INF/views/message/showMessages.jsp) .. code-block:: jsp Result Message Example

    Result Message

    Messages1

    Messages2

    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | 属性名が"messages1"である\ ``ResultMessages``\ を表示する。 * - | (2) - | 属性名が"messages2"である\ ``ResultMessages``\ を表示する。 ブラウザで表示すると、以下のように出力される。 .. figure:: ./images_MessageManagement/message-management-multiple-messages.jpg :width: 80% 業務例外メッセージの表示 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | \ ``org.terasoluna.gfw.common.exception.BusinessException``\ と\ ``org.terasoluna.gfw.common.exception.ResourceNotFoundException``\ は | 内部で\ ``ResultMessages``\ を保持している。 | 業務例外メッセージを表示する場合は、Serviceクラスで\ ``ResultMessages``\ を設定した\ ``BusinessException``\ をスローすること。 | Controllerクラスでは\ ``BusinessException``\ をキャッチし、例外中の結果メッセージをModelに追加する。 * Serviceクラス .. code-block:: java @Service @Transactional public class UserServiceImpl implements UserService { // omitted public void create(...) { // omitted... if (...) { // illegal state! ResultMessages messages = ResultMessages.error() .add("e.ex.an.9001"); // (1) throw new BusinessException(messages); } } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | エラーメッセージを\ ``ResultMessages``\ で作成し、\ ``BusinessException``\ に設定する。 * Controllerクラス .. code-block:: java @RequestMapping(value = "create", method = RequestMethod.POST) public String create(@Validated UserForm form, BindingResult result, Model model) { // omitted try { userService.create(user); } catch (BusinessException e) { ResultMessages messages = e.getResultMessages(); // (1) model.addAttribute(messages); return "user/createForm"; } // omitted } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | \ ``BusinessException``\ が保持する\ ``ResultMessages``\ を取得し、Modelに追加する。 通常、エラーメッセージ表示する場合は、Controllerで\ ``ResultMessages``\ オブジェクトを作成するのではなく、 こちらの方法を使用する。 | How to extend -------------------------------------------------------------------------------- 独自メッセージタイプを作成する ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | メッセージタイプを追加したい場合の、独自メッセージタイプ作成方法について説明する。 | 通常は、用意されているメッセージタイプのみで十分であるが、採用しているCSSライブラリによっては | メッセージタイプを追加したい場合がある。例えば"notice"というメッセージタイプを追加する場合を説明する。 | まず、以下のように\ ``org.terasoluna.gfw.common.message.ResultMessageType``\ インタフェースを実装した | 独自メッセージタイプクラスを作成する。 .. code-block:: java import org.terasoluna.gfw.common.message.ResultMessageType; public enum ResultMessageTypes implements ResultMessageType { // (1) NOTICE("notice"); private ResultMessageTypes(String type) { this.type = type; } private final String type; @Override public String getType() { // (2) return this.type; } @Override public String toString() { return this.type; } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | \ ``ResultMessageType``\ インタフェースを実装したEnumを定義する。定数オブジェクトで作成してもよいが、Enumで作成することを推奨する。 * - | (2) - | \ ``getType``\ の返り値が出力されるCSSのclass名に対応する。 | このメッセージタイプを使用して以下のように\ ``ResultMessages``\ を作成する。 .. code-block:: java ResultMessages messages = new ResultMessages(ResultMessageTypes.NOTICE) // (1) .add("w.ex.an.2001"); model.addAttribute(messages); .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | \ ``ResultMessages``\ のコンストラクタに対象の\ ``ResultMessageType``\ を指定する。 この場合、\ ```` \ で以下のようなHTMLが出力される。 .. code-block:: html
    • The recommended change interval has passed password. Please change your password.
    \ .. tip:: 拡張方法は、\ ``org.terasoluna.gfw.common.message.StandardResultMessageType``\ が参考になる。 | Appendix -------------------------------------------------------------------------------- .. _message-management-messagepanel-attribute: タグの属性変更 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ ````\ タグには、表示形式を変更する属性がいくつか用意されている。 .. tabularcolumns:: |p{0.25\linewidth}|p{0.55\linewidth}|p{0.20\linewidth}| .. list-table:: \ ````\ タグ 属性一覧 :header-rows: 1 :widths: 25 55 20 * - オプション - 内容 - defaultの設定値 * - panelElement - 結果メッセージ表示パネルの要素 - div * - panelClassName - 結果メッセージ表示パネルのCSS class名。 - alert * - panelTypeClassPrefix - CSS class名の接頭辞 - alert- * - messagesType - メッセージタイプ。この属性が設定された場合。設定されたメッセージタイプが\ ``ResultMessages``\ がもつメッセージタイプより優先されて使用される。 - * - outerElement - 結果メッセージ一覧を構成するHTMLの外側のタグ - ul * - innerElement - 結果メッセージ一覧を構成するHTMLの内側のタグ - li * - disableHtmlEscape - | HTMLエスケープ処理を無効化するためのフラグ。 | \ ``true``\ を指定する事で、出力するメッセージに対してHTMLエスケープ処理が行われなくなる。 | この属性は、出力するメッセージにHTMLを埋め込むことで、メッセージの装飾などができるようにするために用意している。 | **trueを指定する場合は、XSS対策が必要な文字がメッセージ内に含まれない事が保証されていること。** | | terasoluna-gfw-web 1.0.1.RELEASE以上で利用可能な属性である。 - ``false`` 例えば、CSSフレームワーク"BlueTrip"では以下のようなCSSが用意されている。 .. code-block:: css .error,.notice,.success { padding: .8em; margin-bottom: 1.6em; border: 2px solid #ddd; } .error { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; } .notice { background: #FFF6BF; color: #514721; border-color: #FFD324; } .success { background: #E6EFC2; color: #264409; border-color: #C6D880; } | このCSSを使用したい場合、\ ``
    ...
    ``\ というようにメッセージが出力されてほしい。 | この場合、\ ````\ タグを以下のように使用すればよい(Controllerは修正不要である)。 .. code-block:: jsp 出力されるHTMLは以下のようになる。 .. code-block:: html
    • There are inconsistencies in the data.
    ブラウザで表示すると、以下のように出力される。 .. figure:: ./images_MessageManagement/message-management-bluetrip-error.jpg :width: 80% メッセージ一覧を表示するために\ ``
      ``\ タグを使用したくない場合は、 \ ``outerElement``\ 属性と\ ``innerElement``\ 属性を使用することでカスタマイズできる。 以下のように属性を設定した場合は、 .. code-block:: jsp 次のようにHTMLが出力される。 .. code-block:: html
      There are inconsistencies in the data. Cannot upload, Because the file size must be less than 1,024MB.
      以下のようCSSを設定することで、 .. code-block:: css .alert > span { display: block; /* (1) */ } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | "alert"クラスの要素の子となる\ ````\ タグをブロックレベル要素にする。 ブラウザで次のように表示される。 .. figure:: ./images_MessageManagement/message-management-messagespanel-span.jpg :width: 60% | disableHtmlEscape属性を\ ``true``\にした場合、以下のような出力イメージにする事ができる。 | 下記の例では、メッセージの一部のフォントを「16pxの赤字」に装飾している。 - jsp .. code-block:: jsp :emphasize-lines: 4 - properties .. code-block:: properties i.ex.od.0001 = Please confirm order content. If this orders submitted, cannot cancel. - 出力イメージ .. figure:: ./images_MessageManagement/message-management-disableHtmlEscape-true.png :width: 100% disableHtmlEscape属性が\ ``false``\(デフォルト)の場合は、HTMLエスケープされて以下のような出力となる。 .. figure:: ./images_MessageManagement/message-management-disableHtmlEscape-false.png :width: 100% ResultMessagesを使用しない結果メッセージの表示 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ ````\ タグは\ ``ResultMessages``\ オブジェクト以外にも * ``java.lang.String`` * ``java.lang.Exception`` * ``java.util.List`` オブジェクトも出力できる。 | 通常は\ ````\ タグは\ ``ResultMessages``\ オブジェクトの出力用に使用するが、 | フレームワークがリクエストスコープに設定した文字列(エラーメッセージなど)を表示する場合にも使用できる。 | 例えば、Spring Securityのデフォルトの設定で使用される、\ ``org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler``\ では、認証エラー時に発生した例外オブジェクトを\ ``SPRING_SECURITY_LAST_EXCEPTION``\ という属性名で、リダイレクト時はセッション、フォワード時はリクエストスコープに格納する。 | この例外メッセージを、結果メッセージ同様に\ ````\ タグで出力したい場合は、以下のように設定すればよい。 .. code-block:: jsp Login
      Login Form
      .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - 項番 - 説明 * - | (1) - | 結果メッセージ表示用のCSSを再掲する。実際はCSSファイルに記述することを強く推奨する。 * - | (2) - | ``Exception``\ オブジェクトが格納されている属性名を\ ``messagesAttributeName``\ 属性で指定する。 | また、\ ``ResultMessages``\ オブジェクトとは異なり、メッセージタイプの情報をもたないため、 | \ ``messagesType``\ 属性で、明示的に、メッセージタイプを指定する必要がある。 認証エラー時に出力されるHTMLは .. code-block:: html
      • Bad credentials
      であり、ブラウザでは以下のように出力される。 .. figure:: ./images_MessageManagement/message-management-login-error.jpg :width: 60% \ .. tip:: ログイン用のJSPの内容については、\ :doc:`../../Security/Authentication`\ を参照されたい。 .. _message-management-messagekeysgen: メッセージキー定数クラスの自動生成ツール ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | これまでの例ではメッセージキーを文字列のハードコードで設定していたが、 | メッセージキーは定数クラスにまとめることを推奨する。 | ここでは、簡易ツールとして、propertiesファイルからメッセージキー定数クラスを | 自動生成するプログラムおよび使用方法を紹介する。必要に応じてカスタマイズして利用されたい。 .. raw:: latex \newpage #. メッセージキー定数クラスの作成 まず空のメッセージキー定数クラスを作成する。ここでは\ ``com.example.common.message.MessageKeys``\ とする。 .. code-block:: java package com.example.common.message; public class MessageKeys { } #. 自動生成クラスの作成 次に\ ``MessageKeys``\ クラスと同じパッケージに\ ``MessageKeysGen``\ クラスを作成し、以下のように記述する。 .. code-block:: java package com.example.common.message; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; import org.springframework.core.io.ClassPathResource; public class MessageKeysGen { public static void main(String[] args) throws IOException { // message properties file Class targetClazz = MessageKeys.class; File output = new File("src/main/java/" + targetClazz.getName() .replaceAll(Pattern.quote("."), "/") + ".java"); try (InputStream inputStream = new ClassPathResource("i18n/application-messages.properties") .getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter pw = new PrintWriter(FileUtils.openOutputStream( output))) { pw.println("package " + targetClazz.getPackage().getName() + ";"); pw.println("/**"); pw.println(" * Message Id"); pw.println(" */"); pw.println("public class " + targetClazz.getSimpleName() + " {"); String line; while ((line = bufferedReader.readLine()) != null) { String[] vals = line.split("=", 2); if (vals.length > 1) { String key = vals[0].trim(); String value = vals[1].trim(); pw.println(" /** " + key + "=" + value + " */"); pw.println(" public static final String " + key .toUpperCase().replaceAll(Pattern.quote("."), "_") .replaceAll(Pattern.quote("-"), "_") + " = \"" + key + "\";"); } } pw.println("}"); pw.flush(); } } } #. メッセージプロパティファイルの用意 src/main/resource/i18m/application-messages.propertiesにメッセージを定義する。ここでは例として、以下のように設定する。 .. code-block:: properties i.ex.an.0001={0} upload completed. w.ex.an.2001=The recommended change interval has passed password. Please change your password. e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. e.ex.an.9001=There are inconsistencies in the data. #. 自動生成クラスの実行 .. figure:: ./images_MessageManagement/message-management-messagekeysgen.png :width: 60% ``MessageKeys``\ クラスが、以下のように上書きされる。 .. code-block:: java package com.example.common.message; /** * Message Id */ public class MessageKeys { /** i.ex.an.0001={0} upload completed. */ public static final String I_EX_AN_0001 = "i.ex.an.0001"; /** w.ex.an.2001=The recommended change interval has passed password. Please change your password. */ public static final String W_EX_AN_2001 = "w.ex.an.2001"; /** e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. */ public static final String E_EX_AN_8001 = "e.ex.an.8001"; /** e.ex.an.9001=There are inconsistencies in the data. */ public static final String E_EX_AN_9001 = "e.ex.an.9001"; } \ .. raw:: latex \newpage