From 0698633156b5e55c0c0d5befe5d743ef5d363175 Mon Sep 17 00:00:00 2001
From: rnakagawa16 <144891521+rnakagawa16@users.noreply.github.com>
Date: Thu, 26 Dec 2024 10:56:44 +0900
Subject: [PATCH] =?UTF-8?q?=E3=83=AD=E3=82=B0=E5=87=BA=E5=8A=9B=E8=A8=AD?=
=?UTF-8?q?=E5=AE=9A=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E4=BF=AE=E6=AD=A3?=
=?UTF-8?q?=E3=81=A8=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88?=
=?UTF-8?q?=E3=81=AE=E8=BF=BD=E5=8A=A0=20(#1697)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* メッセージプロパティを各サブプロジェクトで管理するよう変更する
* 使用していないimportの削除
* メッセージコードをフロントエンドに合わせて頭文字を小文字にする
* フロントエンド側のメッセージ管理機能実装
* バックエンド側のエラーメッセージ出力を実装
* フロントエンド側のメッセージ管理機能の実装
* 起動方法の修正
* テスト時の警告解除
* type-checkの警告対応
* typecheckの警告回避と日英対応のメッセージ作成
* エラーハンドリング機能の修正
* if文の修正
* ドキュメントの追加
* ドキュメントの追加
* エラーメッセージに関する記載の修正
* 入力値検証のドキュメント修正
* ブラウザーの言語設定の取得方法修正
* ドキュメント指摘事項の修正
* クリップボード機能の修正
* textlintエラーへの対応
* 入力値検証に関するドキュメントの修正
* ドキュメント指摘事項の修正
* ドキュメントのimport文の削除
* 起動方法の修正
* ドキュメントのアプリ起動方法を記載
* 冗長な文章を修正
* ハイライトを修正
* 指摘事項と軽微なドキュメントの修正
* 変数名の修正
* log4jの設定をエントリーポイントプロジェクトに移動
* log4j.xmlに関するドキュメントを追記する
* ログドキュメントの修正
* batchアプリケーションの設定
* メッセージ管理の部分を削除
* ロギングライブラリの除外設定に関するドキュメントを修正
* 除外設定のドキュメントにおけるライブラリの記載を修正
* gradle の最終作成結果にlog4j用のライブラリを追加する。
* バージョン定義一元化のドキュメントにlog4j 2のライブラリの記載を追加
* ルートプロジェクトの除外設定を削除
* auth-backendのlog4j 2の設定をエントリーポイントとなるサブプロジェクトに移動
---
.github/CONTRIBUTING.md | 2 +-
.textlintrc | 2 +-
cspell.json | 3 +
.../error-message-delivery-dark.drawio | 229 ++++++++++++++++++
.../error-message-delivery-light.drawio | 229 ++++++++++++++++++
.../frontend-application/index.md | 4 +
.../global-function/exception-handling.md | 60 +++++
.../message-management-policy.md | 135 ++++++++++-
.../logging-policy.md | 29 +++
.../message-management-policy.md | 72 +++++-
.../application-core-project-settings.md | 26 ++
.../batch-project-settings.md | 29 +++
.../infrastructure-project-settings.md | 26 ++
.../project-version-control.md | 18 +-
.../system-common-project-settings.md | 26 ++
.../web-project-settings.md | 76 ++++++
.../guidebooks/how-to-develop/vue-js/index.md | 1 +
.../how-to-develop/vue-js/input-validation.md | 58 +++--
.../vue-js/message-management.md | 167 +++++++++++++
.../vue-js/optional-packages.md | 4 +
.../error-message-delivery-dark.png | Bin 0 -> 240913 bytes
.../error-message-delivery-light.png | Bin 0 -> 239984 bytes
documents/contents/index.md | 10 +-
documents/mkdocs.yml | 1 +
.../auth-backend/system-common/build.gradle | 1 -
.../auth-backend/web/build.gradle | 1 +
.../src/main/resources/log4j2.xml | 0
.../dressca-backend/.vscode/launch.json | 2 +-
.../application-core/build.gradle | 1 -
.../AssetApplicationService.java | 6 +-
.../CatalogApplicationService.java | 15 +-
.../OrderApplicationService.java | 6 +-
.../ShoppingApplicationService.java | 17 +-
.../assets/AssetNotFoundException.java | 4 +-
.../baskets/BasketNotFoundException.java | 4 +-
.../CatalogItemInBasketNotFoundException.java | 4 +-
.../catalog/CatalogNotFoundException.java | 6 +-
.../constant/ExceptionIdConstant.java | 25 ++
.../constant/MessageIdConstant.java | 37 +++
.../order/EmptyBasketOnCheckoutException.java | 4 +-
.../order/OrderNotFoundException.java | 4 +-
.../resources/application-common.properties | 4 +-
.../applicationcore/messages.properties | 18 ++
.../AssetApplicationServiceTest.java | 2 +
.../CatalogApplicationServiceTest.java | 2 +
.../OrderApplicationServiceTest.java | 2 +
.../ShoppingApplicationServiceTest.java | 2 +
.../dressca-backend/batch/build.gradle | 1 +
.../src/main/resources/log4j2.xml | 0
samples/web-csr/dressca-backend/build.gradle | 5 -
.../config/checkstyle/suppressions.xml | 2 +
.../infrastructure/build.gradle | 7 +
.../system-common/build.gradle | 1 -
.../constant/CommonExceptionIdConstant.java | 13 +
.../constant/ExceptionIdConstant.java | 29 ---
.../constant/MessageIdConstant.java | 59 -----
.../exception/response/ErrorResponse.java | 60 -----
.../resources/application-common.properties | 2 +-
.../src/main/resources/messages.properties | 24 --
.../systemcommon/messages.properties | 2 +
.../web-csr/dressca-backend/web/build.gradle | 11 +-
.../web/constant/ProblemDetailsConstant.java | 7 +-
.../web/controller/AssetsController.java | 19 +-
.../web/controller/BasketItemController.java | 55 ++++-
.../web/controller/OrderController.java | 25 +-
.../ExceptionHandlerControllerAdvice.java | 49 ++--
...LocalExceptionHandlerControllerAdvice.java | 92 -------
.../advice/ProblemDetailsCreation.java | 60 +++++
.../dressca/web/log/ErrorMessageBuilder.java | 18 +-
.../resources/application-common.properties | 4 +
.../src/main/resources/application.properties | 2 +-
.../web/src/main/resources/log4j2.xml | 24 ++
.../ExceptionHandlerControllerAdviceTest.java | 44 ++--
...lExceptionHandlerControllerAdviceTest.java | 44 ++--
.../dressca-frontend/consumer/package.json | 1 +
.../dressca-frontend/consumer/src/App.vue | 2 +-
.../consumer/src/api-client/index.ts | 8 +-
.../src/components/basket/BasketItem.vue | 3 +-
.../components/common/NotificationToast.vue | 58 ++++-
.../consumer/src/config/yup.config.ts | 20 +-
.../src/locales/en/messageList_en.json | 25 ++
.../src/locales/en/validationTextList_en.json | 4 +
.../consumer/src/locales/i18n.ts | 25 ++
.../src/locales/ja/messageList_ja.json | 25 ++
.../src/locales/ja/validationTextList_ja.json | 4 +
.../dressca-frontend/consumer/src/main.ts | 4 +-
.../notification/notificationService.ts | 11 +-
.../error-handler/custom-error-handler.ts | 99 ++++++--
.../src/shared/error-handler/custom-error.ts | 18 +-
.../error-handler/error-message-format.ts | 8 +
.../src/stores/notification/notification.ts | 21 +-
.../src/validation/validation-items.ts | 9 +-
.../src/views/authentication/LoginView.vue | 8 +-
.../consumer/src/views/basket/BasketView.vue | 101 ++++++--
.../src/views/catalog/CatalogView.vue | 62 ++++-
.../consumer/src/views/error/ErrorView.vue | 8 +-
.../src/views/ordering/CheckoutView.vue | 40 ++-
.../consumer/src/views/ordering/DoneView.vue | 38 ++-
.../dressca-frontend/package-lock.json | 67 ++++-
99 files changed, 2156 insertions(+), 546 deletions(-)
create mode 100644 documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-dark.drawio
create mode 100644 documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-light.drawio
create mode 100644 documents/contents/guidebooks/how-to-develop/vue-js/message-management.md
create mode 100644 documents/contents/images/app-architecture/client-side-rendering/error-message-delivery-dark.png
create mode 100644 documents/contents/images/app-architecture/client-side-rendering/error-message-delivery-light.png
rename samples/azure-ad-b2c-sample/auth-backend/{system-common => web}/src/main/resources/log4j2.xml (100%)
create mode 100644 samples/web-csr/dressca-backend/application-core/src/main/java/com/dressca/applicationcore/constant/ExceptionIdConstant.java
create mode 100644 samples/web-csr/dressca-backend/application-core/src/main/java/com/dressca/applicationcore/constant/MessageIdConstant.java
create mode 100644 samples/web-csr/dressca-backend/application-core/src/main/resources/applicationcore/messages.properties
rename samples/web-csr/dressca-backend/{system-common => batch}/src/main/resources/log4j2.xml (100%)
create mode 100644 samples/web-csr/dressca-backend/system-common/src/main/java/com/dressca/systemcommon/constant/CommonExceptionIdConstant.java
delete mode 100644 samples/web-csr/dressca-backend/system-common/src/main/java/com/dressca/systemcommon/constant/ExceptionIdConstant.java
delete mode 100644 samples/web-csr/dressca-backend/system-common/src/main/java/com/dressca/systemcommon/constant/MessageIdConstant.java
delete mode 100644 samples/web-csr/dressca-backend/system-common/src/main/java/com/dressca/systemcommon/exception/response/ErrorResponse.java
delete mode 100644 samples/web-csr/dressca-backend/system-common/src/main/resources/messages.properties
create mode 100644 samples/web-csr/dressca-backend/system-common/src/main/resources/systemcommon/messages.properties
delete mode 100644 samples/web-csr/dressca-backend/web/src/main/java/com/dressca/web/controller/advice/LocalExceptionHandlerControllerAdvice.java
create mode 100644 samples/web-csr/dressca-backend/web/src/main/java/com/dressca/web/controller/advice/ProblemDetailsCreation.java
create mode 100644 samples/web-csr/dressca-backend/web/src/main/resources/log4j2.xml
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/locales/en/messageList_en.json
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/locales/en/validationTextList_en.json
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/locales/i18n.ts
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/locales/ja/messageList_ja.json
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/locales/ja/validationTextList_ja.json
create mode 100644 samples/web-csr/dressca-frontend/consumer/src/shared/error-handler/error-message-format.ts
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index d952519f4..dc646a0f2 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -24,7 +24,7 @@ Issue や Discussions に対して追加の説明や質問がある場合は、
これらでは解決できない場合、 Discussions の [Q&A](https://github.com/AlesInfiny/maia/discussions/categories/05-q-a) より質問をお寄せください。
質問を投稿する場合、直面していることについてできる限り多くの情報を提供してください。
-可能な限りスピーディーに対応いたします。
+可能な限り迅速に対応いたします。
ただし、質問に対する回答が常に得られることを期待しないでください。
## 本プロジェクトに対するコントリビュート
diff --git a/.textlintrc b/.textlintrc
index 070fe80de..fa98dd79b 100644
--- a/.textlintrc
+++ b/.textlintrc
@@ -358,6 +358,7 @@
"状態",
"ジョッキー",
"ジレンマ",
+ "迅速",
"スキャナー",
"スキーマ",
"スクエア",
@@ -377,7 +378,6 @@
"ストーブ",
"ストーリー",
"スパイウェア",
- "スピーディー",
"スピード",
"スペイン",
"スポーツ",
diff --git a/cspell.json b/cspell.json
index 03fa44d09..234003a71 100644
--- a/cspell.json
+++ b/cspell.json
@@ -30,6 +30,8 @@
"words": [
"Adoptium",
"AlesInfiny",
+ "Appender",
+ "Appenders",
"BIPROGY",
"Checkstyle",
"Corretto",
@@ -44,6 +46,7 @@
"JaCoCo",
"JDBC",
"linenums",
+ "Logback",
"markdownlint",
"mkdocs",
"Mockito",
diff --git a/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-dark.drawio b/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-dark.drawio
new file mode 100644
index 000000000..6a1e29c50
--- /dev/null
+++ b/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-dark.drawio
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-light.drawio b/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-light.drawio
new file mode 100644
index 000000000..3a77c9e75
--- /dev/null
+++ b/documents/_materials/images/app-architecture/client-side-rendering/error-message-delivery-light.drawio
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/documents/contents/app-architecture/client-side-rendering/frontend-application/index.md b/documents/contents/app-architecture/client-side-rendering/frontend-application/index.md
index caa59229f..fb7e1b3e9 100644
--- a/documents/contents/app-architecture/client-side-rendering/frontend-application/index.md
+++ b/documents/contents/app-architecture/client-side-rendering/frontend-application/index.md
@@ -155,13 +155,17 @@ Vue.js プロジェクトのフォルダー構成は、ブランクプロジェ
├─ cypress/ ------------------ cypress による E2E テストに関するファイルを格納します。
├─ public/ ------------------- メディアファイルや favicon など静的な資産を格納します。
├─ src/
+│ ├─ api-client/ ------------ API クライアントの設定ファイルを格納します。
│ ├─ assets/ ---------------- コードや動的ファイルが必要とするCSSや画像などのアセットを格納します。
│ ├─ components/ ------------ 単体で自己完結している再利用性の高い vue コンポーネントなどを格納します。
│ ├─ config/ ---------------- 設定ファイルを格納します。
│ ├─ generated/ ------------- 自動生成されたファイルを格納します。
+│ ├─ locales/ --------------- メッセージ管理に関するファイルを格納します。
│ ├─ router/ ---------------- ルーティング定義を格納します。
│ ├─ services/ -------------- サービスに関するファイルを格納します。
+│ ├─ shared/ ---------------- アプリケーション全体で再利用する共通機能のファイルを格納します。
│ ├─ stores/ ---------------- store に関するファイルを格納します。
+│ ├─ validation/ ------------ 一元化するバリデーション定義ファイルを格納します。
│ ├─ views/ ----------------- ルーティングで指定される vue ファイルを格納します。またページ固有の挙動などもここに含めます。
│ ├─ App.vue
│ └─ main.ts
diff --git a/documents/contents/app-architecture/client-side-rendering/global-function/exception-handling.md b/documents/contents/app-architecture/client-side-rendering/global-function/exception-handling.md
index 14ada9c8b..7099e8f4b 100644
--- a/documents/contents/app-architecture/client-side-rendering/global-function/exception-handling.md
+++ b/documents/contents/app-architecture/client-side-rendering/global-function/exception-handling.md
@@ -3,6 +3,8 @@ title: CSR 編
description: クライアントサイドレンダリングを行う Web アプリケーションの アーキテクチャについて解説します。
---
+
+
# 例外処理方針 {#top}
バックエンドアプリケーションで発生するシステム例外や業務例外は、例外フィルターによって捕捉します。
@@ -103,3 +105,61 @@ HTTP 通信で発生する例外について、レスポンスやステータス
C->>B: エラー通知
deactivate C
```
+
+### API 通信のエラーレスポンス {#error-response}
+
+API 通信で発生した例外において、バックエンドから返却されるエラーレスポンスには、 [ProblemDetails :material-open-in-new:](https://www.rfc-editor.org/rfc/rfc9457.html){ target=_blank } に基づくレスポンスボディーを含みます。
+
+ProblemDetails は、 HTTP API のエラーレスポンスを標準化するための構造体であり、以下のプロパティで定義されています。
+
+| 項目 | プロパティ名 | 推奨レベル | 内容 |
+| ---------------------------- | ------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 簡易メッセージ | title | 必須 | 人間が読める形式で提供されます。 |
+| 詳細メッセージ | detail | 本番環境は非推奨 | スタックトレースなどを含めます。開発環境では生産性向上を目的に含めることを推奨しますが、本番環境では使用しません。開発環境と本番環境で構成を変更することが難しい場合には detail を使用しないよう統一することも検討してください。 |
+| ステータスコード | status | 任意 | HTTP エラーのステータスコードです。 |
+| 詳細 URL | type | 推奨 | エラーを説明する詳細 Web ドキュメントがある場合、ユーザーが参照する URL を追加します。 |
+| 問題が発生したリソースの URI | instance | 任意 | 問題の発生場所を示す URI です。リクエスト先と異なるリソースが問題の発生したリソースである場合、実装の詳細やデータなどの内部情報が漏洩する可能性があるため、追加には注意が必要です。 |
+| 任意のパラメータ | | 任意 | 拡張メンバーです。必要に応じて ProblemDetails のプロパティを拡張する場合に利用します。 |
+
+AlesInfiny Maia OSS Edition では、上記のプロパティに加えて拡張メンバーとして以下を定義しています。
+
+- exceptionId
+
+ 例外 ID 。メッセージファイルからエラーメッセージを取得するためのメッセージコードとして利用します。
+
+- exceptionValues
+
+ 例外値。例外 ID から取得したエラーメッセージ内のパラメーターに代入する値として利用します。
+
+クライアントサイドでポップアップやトースト通知などを用いてエラー通知を実装する場合には、 ProblemDetails の各プロパティの内容を表示します。
+
+#### エラーレスポンスの例 {#example-of-error-response}
+
+説明したエラーレスポンスの例を以下に示します。
+
+```json title="開発環境の場合のエラーレスポンス"
+HTTP/1.1 400 Bad Request
+Content-Type: application/json; charset=utf-8
+
+{
+ "type": "https://hoge.com/error/catalogItemIdDoesNotExistInBasket",
+ "title": "業務エラーが発生しました。",
+ "status": 400,
+ "detail": "dressca.applicationcore.baskets.CatalogItemInBasketNotFoundException: 業務エラーが発生しました。 ###以下スタックトレースは省略###",
+ "exceptionId": "catalogItemIdDoesNotExistInBasket",
+ "exceptionValues": ["1 ###買い物かごID###", "10 ###商品ID###"]
+}
+```
+
+```json title="本番環境の場合のエラーレスポンス"
+HTTP/1.1 400 Bad Request
+Content-Type: application/json; charset=utf-8
+
+{
+ "type": "https://hoge.com/error/catalogItemIdDoesNotExistInBasket",
+ "title": "業務エラーが発生しました。",
+ "status": 400,
+ "exceptionId": "catalogItemIdDoesNotExistInBasket",
+ "exceptionValues": ["1 ###買い物かごID###", "10 ###商品ID###"]
+}
+```
diff --git a/documents/contents/app-architecture/client-side-rendering/global-function/message-management-policy.md b/documents/contents/app-architecture/client-side-rendering/global-function/message-management-policy.md
index 4ee181928..89675769a 100644
--- a/documents/contents/app-architecture/client-side-rendering/global-function/message-management-policy.md
+++ b/documents/contents/app-architecture/client-side-rendering/global-function/message-management-policy.md
@@ -9,5 +9,136 @@ Java アプリケーションのメッセージ管理方針については、以
- [Java アプリケーションの処理方式 - メッセージ管理方針](../../../app-architecture/overview/java-application-processing-system/message-management-policy.md#message-management-policy)
-フロントエンドアプリケーションでは、特別なメッセージ管理しません。
-画面内に出力するメッセージやラベルは、各画面やソースコード内に個別に実装したものを使用します。
+フロントエンドアプリケーションにおけるメッセージとは、画面や帳票等に表示する固定文言、またはユーザーの画面操作の結果に応じて表示する動的文言を指します。
+
+## メッセージパターン {#message-pattern}
+
+フロントエンドアプリケーションにおけるメッセージパターンとメッセージの表示内容を以下に示します。
+
+| パターン | 表示内容 | 表示例 |
+| -------------------- | -------------------- | ------------------------------------------------------------ |
+| 処理メッセージ | 処理の確認 | 注文内容を確認して「注文を確定する」ボタンを押してください。 |
+| | 正常終了 | 注文が完了しました。 |
+| | 業務エラー | カートに追加できませんでした。 |
+| | | 商品の削除に失敗しました。 |
+| | システムエラー | サーバーエラーが発生しました。 |
+| | | ネットワークエラーが発生しました。 |
+| 入力値検証メッセージ | 単項目チェックエラー | 値を入力してください |
+| | 相関チェックエラー | パスワードと確認用パスワードが一致しません |
+| ラベル | 画面のタイトル | Dressca |
+| | 画面の項目名 | 合計 / 送料 |
+| | UI ラベル | 注文を確定する |
+
+## メッセージの管理単位 {#management-unit}
+
+各メッセージの用途を明確にするため、前述したメッセージパターンごとにメッセージを管理します。
+AlesInfiny Maia OSS Edition における、メッセージパターンごとのメッセージ管理方針は以下の通りです。
+
+- 処理メッセージ
+
+ 処理メッセージ管理用のファイルを定義して一括で管理します。
+
+ 処理メッセージは変更や追加の要求が多く、一か所で管理することによりメンテナンスが容易になります。
+
+- 入力値検証メッセージ
+
+ 入力値検証メッセージ管理用のファイルを定義して一括で管理します。
+
+ 入力値検証メッセージは複数の場所で使用する可能性が高く、ファイルに定義しておくことで再利用が簡単になります。
+ これにより、コードの重複を避けることにつながります。
+
+- ラベル
+
+ 画面内に出力するラベルは各画面やソースコード内に個別に実装したものを使用します。
+
+ ラベルに対してもアプリケーション全体で用語を統一する場合や後述する多言語を実施する場合には、ファイルによるメッセージの一元管理が必要です。
+ しかし、用語の統一は初期の実装やメッセージ管理ファイルの維持にかかるコストが高いです。
+ また、ラベルへの多言語対応は言語設定によって画面のレイアウトが崩れてしまう恐れがあります。
+ そのため、ラベルに対してファイルによるメッセージ管理を導入することは、慎重な検討が必要です。
+
+## メッセージのファイル管理 {#message-file-management}
+
+フロントエンドアプリケーションでは、処理メッセージや入力値検証メッセージは JSON ファイルを利用して管理します。
+JSON ファイルでは、以下のようにメッセージ文字列を識別するメッセージコードとメッセージ文字列本体を key-value で管理します。
+
+``` json title="メッセージの JSON ファイルの定義例"
+{
+ "errorOccurred": "エラーが発生しました。",
+ ...
+}
+```
+
+### メッセージコードの定義 {#message-codes-definition}
+
+前述した JSON ファイルのように、メッセージコードはそのメッセージの内容を簡潔に表す文字列とします。
+このようにすることで、以下のような利点があります。
+
+- 可読性の向上
+
+ 数字のメッセージコードよりも、意味を持つメッセージコードを定義することで直感的で理解しやすい利点があります。
+ 開発者がメッセージコードを見たときに、すぐにそのメッセージの内容や目的を把握できます。
+
+- エラー追跡の効率化
+
+ ログやデバッグ時に、意味を持つコードは問題を迅速に特定することに役立ちます。
+
+- ドキュメント化の簡便さ
+
+ メッセージコードがそのメッセージ内容を簡潔に表していれば、メッセージコードの意味を説明するための追加のドキュメントが不要になることがあります。
+
+### エラーメッセージコードの統一 {#unification-of-message-codes}
+
+エラー発生時のメッセージ整形の流れを以下に示します。
+
+![エラーメッセージ整形の流れ](../../../images/app-architecture/client-side-rendering/error-message-delivery-light.png#only-light){ loading=lazy }
+![エラーメッセージ整形の流れ](../../../images/app-architecture/client-side-rendering/error-message-delivery-dark.png#only-dark){ loading=lazy }
+
+この画像の通り、エラー発生時はバックエンドアプリケーションのエラーログの出力とフロントエンドアプリケーションへのエラーの画面出力が順次実施されます。
+
+そのため、同一の業務エラーやシステムエラーのメッセージコードは、バックエンド側とフロントエンド側で統一します。
+これにより、以下のような利点があります。
+
+- 一貫性の確保
+
+ 統一されたメッセージコードを使用することで、エラーの識別が容易になり、システム全体の一貫性が保たれます。
+
+- デバッグの効率化
+
+ 開発者がエラーを特定しやすくなり、問題解決のスピードが向上します。
+ バックエンドとフロントエンドで同じコードを使用することで、エラーの原因を迅速に特定できます。
+
+OpenAPI 仕様書などの各 JSON ファイルと命名規則を統一するため、メッセージコードをキャメルケースとします。
+それに伴い、フロントエンド側に合わせてバックエンドのプロパティファイルのメッセージコードもキャメルケースで記載します。
+バックエンドのプロパティファイルの設定例は、[こちら](../global-function/message-management-policy.md#message-codes-definition) を確認してください。
+
+### エラーメッセージ内のパラメータ {#parameter-of-error-messages}
+
+以下のように、エラーメッセージの中にはパラメータを含むものがあります。
+
+```json title="パラメータを含むエラーメッセージの例"
+{
+ "assetNotFound": "アセットコード: [0] のアセットが見つかりませんでした。",
+}
+```
+
+パラメータに代入するべき値は、エラーレスポンスに含まれる ProblemDetails の拡張メンバーである `exceptionValues` から取得します。
+ProblemDetails については、[こちら](./exception-handling.md#error-response) を確認してください。
+
+### 多言語対応 {#localization}
+
+メッセージを多言語対応する場合には、それぞれの言語の JSON ファイルを作成し、各言語のメッセージをフォルダーで分割して管理します。
+以下に示すように、フォルダー名は [ISO-639 言語コード :material-open-in-new:](https://www.iso.org/iso-639-language-code){ target=_blank } に基づき、その言語を表す言語コードとします。
+
+また、各ファイルの末尾には言語コードを付与します。
+
+```terminal linenums="0"
+locales/ ------------------------------------- メッセージ管理を行うコードが配置されるフォルダー
+ ├ en/ ---------------------------------------- 英語メッセージの管理を行うフォルダー
+ │ ├ messageList_en.json ---------------------- 処理の成功や失敗などの結果メッセージを格納する JSON ファイル(英語)
+ │ └ validationTextList_en.json --------------- 入力値検証用のメッセージを格納する JSON ファイル(英語)
+ └ ja/ ---------------------------------------- 日本語メッセージの管理を行うフォルダー
+ ├ messageList_ja.json ---------------------- 処理の成功や失敗などの結果メッセージを格納する JSON ファイル(日本語)
+ └ validationTextList_ja.json --------------- 入力値検証用のメッセージを格納する JSON ファイル(日本語)
+```
+
+メッセージ管理方針に従った機能の実装方法などの詳細については、[こちら](../../../guidebooks/how-to-develop/vue-js/message-management.md) を確認してください。
diff --git a/documents/contents/app-architecture/overview/java-application-processing-system/logging-policy.md b/documents/contents/app-architecture/overview/java-application-processing-system/logging-policy.md
index 9bc0cad1b..8bc940ba6 100644
--- a/documents/contents/app-architecture/overview/java-application-processing-system/logging-policy.md
+++ b/documents/contents/app-architecture/overview/java-application-processing-system/logging-policy.md
@@ -93,3 +93,32 @@ AlesInfiny Maia で定義するログの種類は以下の通りです。
AlesInfiny Maia では、 Java アプリケーションのロギングライブラリとして [Apache Log4j 2 :material-open-in-new:](https://logging.apache.org/log4j/2.x/){ target=_blank } を使用します。
またロギングファサードとして [SLF4J :material-open-in-new:](https://www.slf4j.org/){ target=_blank } を使用します。
+
+### ログの設定ファイル {#logging-configuration-files}
+
+log4j 2 では、設定ファイルを使用しログの動作を制御します。
+
+ログの設定ファイルは、以下の形式をサポートしています。
+なお、 AlesInfiny Maia では、ログの設定ファイルに XML 形式を採用しています。
+
+- XML
+- JSON
+- YAML
+- Properties
+
+また、 AlesInfiny Maia はマルチプロジェクト構成を採用しています。
+エントリーポイントとなるサブプロジェクトが複数ある場合、それぞれでログ形式を定めることが考えられます。
+
+そのため、以下のようにログの設定ファイルをエントリーポイントとなる各プロジェクトに配置します。
+
+```terminal linenums="0"
+root/ ------------------------------------------ root フォルダー
+ ├ webapp1/ ---------------------------------- 管理アプリのエントリーポイントとなるサブプロジェクト
+ │ └ src/main/resource/ ------------------------ 設定ファイルを一元管理するフォルダー
+ │ └ log4j2.xml ------------------------------ ログの設定ファイル
+ └ webapp2/ ------------------------------- コンシューマーアプリのエントリーポイントとなるサブプロジェクト 2
+ └ src/main/resource/ ------------------------ 設定ファイルを一元管理するフォルダー
+ └ log4j2.xml ------------------------------ ログの設定ファイル
+```
+
+log4j2.xml の具体的な設定については、[こちら](../../../guidebooks/how-to-develop/java/sub-project-settings/web-project-settings.md#logging-configuration) を確認してください。
diff --git a/documents/contents/app-architecture/overview/java-application-processing-system/message-management-policy.md b/documents/contents/app-architecture/overview/java-application-processing-system/message-management-policy.md
index 0571dba32..fab227489 100644
--- a/documents/contents/app-architecture/overview/java-application-processing-system/message-management-policy.md
+++ b/documents/contents/app-architecture/overview/java-application-processing-system/message-management-policy.md
@@ -3,6 +3,74 @@ title: Java アプリケーションの 処理方式
description: アプリケーションの形態によらず、 Java アプリケーションで 考慮すべき関心事について、実装方針を説明します。
---
-## メッセージ管理方針 {#message-management-policy}
+
-メッセージ文字列は、表記の統一を図る目的にプロパティファイルで管理します。
+# メッセージ管理方針 {#message-management-policy}
+
+フロントエンドアプリケーションのメッセージ管理方針については、以下を参照してください。
+
+- [フロントエンドアプリケーションの処理方式 - メッセージ管理方針](../../client-side-rendering/global-function/message-management-policy.md)
+
+メッセージ文字列は、表記の統一を図ることを目的にプロパティファイルで管理します。
+
+## プロパティファイルの管理 {#property-file-management}
+
+プロパティファイルでは、以下のようにメッセージ文字列を識別するメッセージコードとメッセージ文字列本体をペアで管理します。
+
+```properties title="message.properties の例"
+errorOccurred=エラーが発生しました。
+...
+```
+
+## エラーメッセージコードの統一 {#unification-of-message-codes}
+
+同一の業務エラーやシステムエラーのメッセージコードは、バックエンド側とフロントエンド側で統一します。
+
+詳細については、[こちら](../../client-side-rendering/global-function/message-management-policy.md#unification-of-message-codes) を確認してください。
+
+## メッセージの管理単位 {#management-unit}
+
+以下のように、ビジネスロジックで発生する業務メッセージと共通処理として発生する共通メッセージを分割して各サブプロジェクトで管理します。
+
+```terminal linenums="0"
+root/ ------------------------------------------ root フォルダー
+ ├ application-core/src/main/resource
+ │ └ applicationcore --------------------------- 業務メッセージのプロパティファイルを一括管理するフォルダー
+ │ └ message.properties --------------------- 業務メッセージのプロパティファイル
+ └ system-common/src/main/resource
+ └ systemcommon ------------------------------ 共通メッセージのプロパティファイルを一括管理するフォルダー
+ └ message.properties --------------------- 共通メッセージのプロパティファイル
+```
+
+業務メッセージと共通メッセージとして格納するメッセージの例は以下の通りです。
+
+- 業務メッセージの例
+
+ - 各業務例外発生時にログ出力するためのエラーメッセージ
+ - 業務完了時に正常終了した旨をログに出力するためのメッセージ
+
+- 共通メッセージの例
+
+ - システム例外発生時にログ出力するためのエラーメッセージ
+ - 業務例外やシステム例外の既定メッセージ
+
+## 多言語対応 {#localization}
+
+メッセージを多言語対応する場合には、それぞれの言語のプロパティファイルを作成し、各言語のメッセージをファイルで分割して管理します。
+以下に示すように、各ファイル名は [ISO-639 言語コード :material-open-in-new:](https://www.iso.org/iso-639-language-code){ target=_blank } に基づき、その言語を表す言語コードを末尾に付与します。
+
+```terminal linenums="0"
+root/ ------------------------------------------ root フォルダー
+ ├ application-core/src/main/resource
+ │ └ applicationcore --------------------------- 業務メッセージのプロパティファイルを一括管理するフォルダー
+ │ ├ message_en.properties ------------------ 業務メッセージのプロパティファイル(英語)
+ │ └ message_ja.properties ------------------ 業務メッセージのプロパティファイル(日本語)
+ └ system-common/src/main/resource
+ └ systemcommon ------------------------------ 共通メッセージのプロパティファイルを一括管理するフォルダー
+ ├ message_en.properties ------------------ 共通メッセージのプロパティファイル(英語)
+ └ message_ja.properties ------------------ 共通メッセージのプロパティファイル(日本語)
+```
+
+アプリケーション起動時に使用するメッセージファイルを切り替えることで、開発者に応じた言語を設定します。
+
+メッセージ管理方針に従った機能の実装方法などの詳細については、[こちら](../../../guidebooks/how-to-develop/java/common-project-settings.md) を確認してください。
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/application-core-project-settings.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/application-core-project-settings.md
index f84cdefbf..59af86e69 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/application-core-project-settings.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/application-core-project-settings.md
@@ -22,6 +22,25 @@ dependencies {
}
```
+## ロギングライブラリの除外設定 {#logging-library-exclusion-settings}
+
+
+
+依存関係に記載している `org.springframework.boot:spring-boot-starter` ライブラリは、デフォルトで Logback 用のライブラリである `org.springframework.boot:spring-boot-starter-logging` が推移的依存で追加されます。
+
+
+
+AlesInfiny Maia OSS Edition では、ロギングライブラリとして log4j 2 を使用します。
+そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。
+
+``` groovy title="spring-boot-starter-logging の除外設定"
+configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+}
+```
+
## プロジェクトのビルド方法の設定 {#config-build}
application-core プロジェクトは単体で動作せず、他プロジェクトからライブラリとして呼び出します。
@@ -74,6 +93,13 @@ application-core プロジェクトの `src` 以下にある、 `ApplicationCore
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
+
tasks.named('test') {
useJUnitPlatform()
}
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/batch-project-settings.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/batch-project-settings.md
index 20423973d..f10b8ab7f 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/batch-project-settings.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/batch-project-settings.md
@@ -16,6 +16,8 @@ batch プロジェクトで利用を推奨するライブラリは以下の通
- `spring-boot-starter-batch`: Spring Batch アプリケーションを構築するための依存関係を提供するスターター
+- `spring-boot-starter-log4j2`: Spring Boot アプリケーションで log4j 2 を使用するためのスターター
+
- `spring-batch-test`: Spring Batch アプリケーションのテストのライブラリ
- `spring-boot-starter-test`:Spring Boot アプリケーションをテストするためのスターター
@@ -23,6 +25,7 @@ batch プロジェクトで利用を推奨するライブラリは以下の通
```groovy title="batch/build.gradle"
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
+ implementation 'org.springframework.boot:spring-boot-starter-log4j2'
testImplementation 'org.springframework.batch:spring-batch-test:x.x.x'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
@@ -101,6 +104,25 @@ batch プロジェクトの `src/main/resource` 以下に `application.propertie
そのため、バッチアプリケーションの起動時に [メタデータテーブルを作成するスキーマ :material-open-in-new:](https://spring.pleiades.io/spring-batch/reference/schema-appendix.html){ target=_blank } を実行するよう指定する必要があります。
バッチ処理のジョブ管理をクラウドサービスや特定のジョブ管理ツールに任せる場合など、Spring Batch で生成されるメタデータテーブルを利用したくない際の対処法は [こちら](../../../../app-architecture/batch-application/batch-application-consideration/without-using-meta-data-table.md) をご覧ください。
+## ロギングライブラリの除外設定 {#logging-library-exclusion-settings}
+
+
+
+依存関係に記載している `org.springframework.boot:spring-boot-starter-batch` ライブラリは、デフォルトで Logback 用のライブラリである `org.springframework.boot:spring-boot-starter-logging` が推移的依存で追加されます。
+
+
+
+AlesInfiny Maia OSS Edition では、ロギングライブラリとして log4j 2 を使用します。
+そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。
+
+``` groovy title="spring-boot-starter-logging の除外設定"
+configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+}
+```
+
## バッチアプリケーションとして動作させる設定 {#config-batch-application}
batch プロジェクトをウェブアプリケーションではなく、バッチアプリケーションとして動作させるためクラスファイルを書き換えます。
@@ -161,6 +183,7 @@ class BatchApplicationTests {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
+ implementation 'org.springframework.boot:spring-boot-starter-log4j2'
testImplementation 'org.springframework.batch:spring-batch-test:x.x.x'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation project(':application-core')
@@ -169,6 +192,12 @@ class BatchApplicationTests {
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
tasks.named('test') {
useJUnitPlatform()
}
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/infrastructure-project-settings.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/infrastructure-project-settings.md
index 5016a7348..3fa387f8c 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/infrastructure-project-settings.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/infrastructure-project-settings.md
@@ -43,6 +43,25 @@ dependencies {
}
```
+## ロギングライブラリの除外設定 {#logging-library-exclusion-settings-infra}
+
+
+
+依存関係に記載している `org.mybatis.spring.boot:mybatis-spring-boot-starter` ライブラリは、デフォルトで Logback 用のライブラリである `org.springframework.boot:spring-boot-starter-logging` が推移的依存で追加されます。
+
+
+
+AlesInfiny Maia OSS Edition では、ロギングライブラリとして log4j 2 を使用します。
+そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。
+
+``` groovy title="spring-boot-starter-logging の除外設定"
+configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+}
+```
+
## プロジェクトのビルド方法の設定 {#config-build}
infrastructure プロジェクトは単体で動作せず、他プロジェクトからライブラリとして呼び出します。
@@ -98,6 +117,13 @@ infrastructure プロジェクトの `src` 以下にある、 `InfrastructureApp
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
+
bootJar {
enabled = false
}
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/project-version-control.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/project-version-control.md
index 971d5763e..8e0ec1614 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/project-version-control.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/project-version-control.md
@@ -112,7 +112,7 @@ buildscript {
Groovy では文字列は一重引用符で囲み、変数を含む文字列は二重引用符で囲んで表現します。
変数を含む文字列を一重引用符で囲むとエラーが出るため、注意して使い分けてください。
-```groovy title="web/build.gradle" hl_lines="3 4 5 9 10 11 12 13"
+```groovy title="web/build.gradle" hl_lines="3 4 5 9 10 11 12 13 14"
plugins {
id 'java'
id 'org.springframework.boot' version "${springBootVersion}"
@@ -123,8 +123,9 @@ plugins {
dependencies {
implementation supportDependencies.spring_boot_starter_web
implementation supportDependencies.h2database
- implementation supportDependencies.springdoc_openapi_starter_webmvc_ui
- implementation supportDependencies.spring_boot_starter_actuator
+ implementation supportDependencies.springdoc_openapi_starter_webmvc_ui
+ implementation supportDependencies.spring_boot_starter_actuator
+ implementation supportDependencies.spring_boot_starter_log4j2
testImplementation supportDependencies.spring_boot_starter_test
implementation project(':application-core')
implementation project(':infrastructure')
@@ -158,8 +159,9 @@ dependencies {
dependencies {
implementation supportDependencies.spring_boot_starter_web
implementation supportDependencies.h2database
- implementation supportDependencies.springdoc_openapi_starter_webmvc_ui
- implementation supportDependencies.spring_boot_starter_actuator
+ implementation supportDependencies.springdoc_openapi_starter_webmvc_ui
+ implementation supportDependencies.spring_boot_starter_actuator
+ implementation supportDependencies.spring_boot_starter_log4j2
testImplementation supportDependencies.spring_boot_starter_test
implementation project(':application-core')
implementation project(':infrastructure')
@@ -167,6 +169,12 @@ dependencies {
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
// OpenAPI 仕様書出力の作業ディレクトリを指定する。
afterEvaluate {
tasks.named("forkedSpringBootRun") {
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/system-common-project-settings.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/system-common-project-settings.md
index 1def70570..cf544cbdd 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/system-common-project-settings.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/system-common-project-settings.md
@@ -10,6 +10,25 @@ system-common プロジェクトの依存ライブラリについては、特に
また、 system-common プロジェクトは他のプロジェクトを参照する想定はないので、他のプロジェクトを依存関係に含める必要はありません。
+## ロギングライブラリの除外設定 {#logging-library-exclusion-settings}
+
+
+
+依存関係に記載している `org.springframework.boot:spring-boot-starter` ライブラリは、デフォルトで Logback 用のライブラリである `org.springframework.boot:spring-boot-starter-logging` が推移的依存で追加されます。
+
+
+
+AlesInfiny Maia OSS Edition では、ロギングライブラリとして log4j 2 を使用します。
+そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。
+
+``` groovy title="spring-boot-starter-logging の除外設定"
+configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+}
+```
+
## プロジェクトのビルド方法の設定 {#config-build}
system-common プロジェクトは単体で動作せず、他プロジェクトからライブラリとして呼び出します。
@@ -61,6 +80,13 @@ system-common プロジェクトの `src` 以下にある、 `SystemCommonApplic
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
+
bootJar {
enabled = false
}
diff --git a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/web-project-settings.md b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/web-project-settings.md
index ddcb44597..c942f1ae7 100644
--- a/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/web-project-settings.md
+++ b/documents/contents/guidebooks/how-to-develop/java/sub-project-settings/web-project-settings.md
@@ -20,6 +20,8 @@ web プロジェクトで利用を推奨するライブラリは以下の通り
- `spring-boot-starter-actuator`: ヘルスチェックを含めたアプリケーション監視・管理機能を構築するためのスターター
+- `spring-boot-starter-log4j2`: Spring Boot アプリケーションで log4j 2 を使用するためのスターター
+
- `spring-boot-starter-test`:Spring Boot アプリケーションをテストするためのスターター
上記のライブラリを依存ライブラリとして、 以下のように `build.gradle` の `dependencies` ブロックに追加します。
@@ -30,6 +32,7 @@ dependencies {
implementation 'com.h2database:h2:x.x.x'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:x.x.x'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
+ implementation 'org.springframework.boot:spring-boot-starter-log4j2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
```
@@ -101,6 +104,71 @@ web プロジェクトの `src/main/resource` 以下に `application.properties`
spring.sql.init.mode=never
```
+## ロギングライブラリの除外設定 {#logging-library-exclusion-settings}
+
+
+
+依存関係に記載している `org.springframework.boot:spring-boot-starter` ライブラリは、デフォルトで Logback 用のライブラリである `org.springframework.boot:spring-boot-starter-logging` が推移的依存で追加されます。
+
+
+
+AlesInfiny Maia OSS Edition では、ロギングライブラリとして log4j 2 を使用します。
+そのため、以下のようにデフォルトのロギングライブラリを依存関係から除外する設定を記述します。
+
+``` groovy title="spring-boot-starter-logging の除外設定"
+configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+}
+```
+
+## ログの設定 {#logging-configuration}
+
+`src/main/resource` に `log4j2.xml` ファイルを配置しログの設定を記述します。
+以下は、ログの設定例です。
+
+```xml title="log4j2.xml"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+log4j2.xml のタグの構成要素は以下の通りです。
+
+- Appenders
+
+ ログの出力先を指定します。
+ ログイベントをどのリソース(コンソール、ファイル、データベースなど)に送信するかを決定します。
+
+- Loggers
+
+ ログのエントリーポイントを指定します。
+ この設定では、どのレベルのメッセージをログに記録するかや、 Appenders のどの要素にメッセージを送信するかなどを指定します。
+
+その他の詳細な設定については、[公式ページ :material-open-in-new:](https://logging.apache.org/log4j/2.x/manual/configuration.html){ target=_blank } を確認してください。
+
## OpenAPI 仕様書の出力設定 {#open-api-specification-output-configuration}
OpenAPI 仕様書のファイルがビルド時に出力されるようプロジェクトファイルを設定します。
@@ -170,6 +238,7 @@ build.dependsOn("generateOpenApiDocs")
implementation 'com.h2database:h2:x.x.x'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:x.x.x'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
+ implementation 'org.springframework.boot:spring-boot-starter-log4j2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation project(':application-core')
implementation project(':infrastructure')
@@ -177,6 +246,13 @@ build.dependsOn("generateOpenApiDocs")
// その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}
+ configurations {
+ all {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ }
+
+
// OpenAPI 仕様書出力の作業ディレクトリを指定する。
afterEvaluate {
tasks.named("forkedSpringBootRun") {
diff --git a/documents/contents/guidebooks/how-to-develop/vue-js/index.md b/documents/contents/guidebooks/how-to-develop/vue-js/index.md
index 60d5ab26a..180c3b11c 100644
--- a/documents/contents/guidebooks/how-to-develop/vue-js/index.md
+++ b/documents/contents/guidebooks/how-to-develop/vue-js/index.md
@@ -16,6 +16,7 @@ Vue.js を用いてフロントエンドアプリケーションを開発する
1. [開発に使用するパッケージ](optional-packages.md)
1. [CSS の設定と CSS フレームワークの適用](css.md)
1. [静的コード分析とフォーマット](static-verification-and-format.md)
+1. [メッセージ管理機能の設定](message-management.md)
1. [入力値検証](input-validation.md)
1. [OpenAPI 仕様書からのクライアントコード生成](create-api-client-code.md)
1. [エラーハンドラーの設定](error-handler-settings.md)
diff --git a/documents/contents/guidebooks/how-to-develop/vue-js/input-validation.md b/documents/contents/guidebooks/how-to-develop/vue-js/input-validation.md
index 72aba8824..31528b1a4 100644
--- a/documents/contents/guidebooks/how-to-develop/vue-js/input-validation.md
+++ b/documents/contents/guidebooks/how-to-develop/vue-js/input-validation.md
@@ -6,36 +6,66 @@ description: Vue.js を用いた クライアントサイドアプリケーシ
# 入力値検証 {#top}
フロントエンドのアーキテクチャに基づき、入力値検証には VeeValidate と yup を使用します。
+また、入力値検証失敗時のメッセージを管理するために、 Vue I18n を使用します。
+メッセージ管理機能の実装方法の詳細に関しては、[こちら](./message-management.md) を確認してください。
## 必要なパッケージのインストール {#install-packages}
-ターミナルを開き、以下のコマンドを実行します。
+ターミナルを開き、対象プロジェクトのワークスペースフォルダーで以下のコマンドを実行します。
```terminal
-npm install vee-validate yup
+npm install vee-validate yup vue-i18n
+```
+
+## メッセージの定義 {#definition-messages}
+
+入力値検証失敗時のメッセージを定義するため、`./src/locales` フォルダーに JSON ファイルを作成し、以下のように記述します。
+メッセージを多言語対応する場合には、それぞれの言語の JSON ファイルを作成し、各言語のメッセージをフォルダーで分割して管理します。
+
+```json title="validationTextList_jp.json"
+{
+ "email": "メールアドレスの形式で入力してください",
+ "required": "値を入力してください"
+}
```
## 入力値検証時の設定 {#settings-validation}
-yup のデフォルトのメッセージは英語であるため、日本語のメッセージを設定します。[アーキテクチャ定義](../../../app-architecture/client-side-rendering/frontend-application/index.md#project-structure) では設定ファイルは `./src/config` フォルダーに集約されるため、ファイル `./src/config/yup.config.ts` を作成し、以下のように記述します。
+各言語設定に基づいた、入力値検証メッセージを読み込みます。
+[アーキテクチャ定義](../../../app-architecture/client-side-rendering/frontend-application/index.md#project-structure) では設定ファイルは `./src/config` フォルダーに集約されるため、ファイル `./src/config/yup.config.ts` を作成し、以下のように記述します。
```typescript title="yup.config.ts"
+import { i18n } from '@/locales/i18n';
import { setLocale } from 'yup';
-setLocale({
- mixed: {
- required: '値を入力してください',
- },
- string: {
- email: 'メールアドレスの形式で入力してください',
- },
-});
+export function configureYup(): void {
+ const { t } = i18n.global;
+ setLocale({
+ mixed: {
+ required: t('required'),
+ },
+ string: {
+ email: t('email'),
+ },
+ });
+}
```
-作成したファイルを読み込むため、 main.ts に import を記述します。
+作成したファイルを読み込むため、 入力値を検証する Vue ファイルのスクリプト構文に以下を記述します。
+
+```vue title="example.vue"
+
```
## 入力値検証の実行 {#input-validation}
diff --git a/documents/contents/guidebooks/how-to-develop/vue-js/message-management.md b/documents/contents/guidebooks/how-to-develop/vue-js/message-management.md
new file mode 100644
index 000000000..c2937e597
--- /dev/null
+++ b/documents/contents/guidebooks/how-to-develop/vue-js/message-management.md
@@ -0,0 +1,167 @@
+---
+title: Vue.js 開発手順
+description: Vue.js を用いた クライアントサイドアプリケーションの 開発手順を説明します。
+---
+
+# メッセージ管理機能の設定 {#top}
+
+フロントエンドのメッセージ管理方針に関するアーキテクチャについては、[こちら](../../../app-architecture/client-side-rendering/global-function/message-management-policy.md) をご確認ください。
+本アーキテクチャに基づき、メッセージ管理機能のライブラリは [Vue I18n :material-open-in-new:](https://kazupon.github.io/vue-i18n/){ target=\_blank } を使用します。
+
+## 必要なパッケージのインストール {#install-packages}
+
+ターミナルを開き、対象プロジェクトのワークスペースフォルダーで以下のコマンドを実行します。
+
+```terminal
+npm install vue-i18n
+```
+
+## 設定方法 {#settings}
+
+本設定で利用するフォルダーの構成は以下の通りです。
+
+```terminal linenums="0"
+
+ └ src/ ------------------------------------------- アプリケーションのソースコードが配置されるフォルダー
+ ├ locales/ ------------------------------------- メッセージ管理を行うコードが配置されるフォルダー
+ │ ├ en/ ---------------------------------------- 英語メッセージの管理を行うフォルダー
+ │ │ ├ messageList_en.json ---------------------- 処理の成功や失敗などの結果メッセージを格納する JSON ファイル(英語)
+ │ │ └ validationTextList_en.json --------------- 入力値検証用のメッセージを格納する JSON ファイル(英語)
+ │ ├ ja/ ---------------------------------------- 日本語メッセージの管理を行うフォルダー
+ │ │ ├ messageList_ja.json ---------------------- 処理の成功や失敗などの結果メッセージを格納する JSON ファイル(日本語)
+ │ │ └ validationTextList_ja.json --------------- 入力値検証用のメッセージを格納する JSON ファイル(日本語)
+ │ └ i18n.ts ------------------------------------ メッセージ管理の設定に関するコード
+ └ main.ts -------------------------------------- 各ライブラリ等を読み込むためのコード
+```
+
+### メッセージファイルの作成 {#creating-message-files}
+
+メッセージに関するファイルは `./src/locales` フォルダーに集約します。
+以下のように、メッセージ本体を格納する JSON ファイルを作成します。
+
+```json title="messageList_jp.json の例"
+{
+ "errorOccurred": "エラーが発生しました。",
+ "businessError": "業務エラーが発生しました。",
+ "loginRequiredError": "ログインしてください。",
+ ...
+}
+```
+
+前述のフォルダー構成の通り、メッセージ管理方針に従って JSON ファイルは以下の 2 つに分割します。
+
+- messageList.json
+
+ 処理の成功や失敗を示す処理メッセージを格納します。
+
+- validationTextList.json
+
+ 入力値検証用のメッセージを格納します。
+ 詳細は [こちら](./input-validation.md#definition-messages) を確認してください。
+
+JSON ファイルでメッセージを管理する際は、メッセージコードとメッセージ本体を key-value で管理します。
+
+### メッセージファイルの読込 {#reading-message-files}
+
+メッセージ本体を格納する JSON ファイルを読み込むために、以下のように `i18n.ts` を実装します。
+
+```ts title="i18n.ts"
+import { createI18n } from "vue-i18n";
+import messageListEN from '@/locales/en/messageList_en.json';
+import messageListJA from '@/locales/ja/messageList_ja.json';
+import validationTextListJA from '@/locales/ja/validationTextList_ja.json';
+import validationTextListEN from '@/locales/en/validationTextList_en.json';
+
+const langPackage = {
+ ja: {
+ ...messageListJA,
+ ...validationTextListJA,
+ },
+ en: {
+ ...messageListEN,
+ ...validationTextListEN,
+ },
+};
+
+const i18n = createI18n({
+ legacy: false,
+ locale: window.navigator.language,
+ fallbackLocale: "en",
+ messages: langPackage,
+});
+
+export { i18n };
+```
+
+メッセージ管理機能を導入するための `createI18n` の引数の役割は以下の通りです。
+
+- legacy
+
+
+
+ createI18n のインスタンスとして、 [Legacy API :material-open-in-new:](https://vue-i18n.intlify.dev/api/legacy.html){ target=\_blank } と [Composition API :material-open-in-new:](https://vue-i18n.intlify.dev/api/composition.html){ target=\_blank } のどちらを利用するか選択します。
+ 本実装では、 Composition API を利用するため、 legacy を false に設定します。
+
+
+- locale
+
+ 使用する言語を指定します。
+ 本実装では、`window.navigator.language` でブラウザーの言語設定を取得します。
+
+- fallbackLocale
+
+ locale に設定した言語がサポートされていない場合に、フォールバックする locale を指定します。
+
+- messages
+
+ locale の言語設定に基づき、利用するメッセージを指定します。
+
+`i18n.ts` の設定をアプリケーションに反映させるため、 `main.ts` に以下のように実装します。
+
+```ts title="main.ts" hl_lines="6 14"
+import { createApp } from "vue";
+import { createPinia } from "pinia";
+import { authenticationGuard } from "@/shared/authentication/authentication-guard";
+import App from "./App.vue";
+import { router } from "./router";
+import { i18n } from "./locales/i18n";
+
+import "@/assets/base.css";
+
+const app = createApp(App);
+
+app.use(createPinia());
+app.use(router);
+app.use(i18n);
+
+authenticationGuard(router);
+
+app.mount("#app");
+```
+
+### メッセージの取得 {#getting-messages}
+
+読み込んだメッセージを取得するためには、 `i18n.ts` を各ファイルでインポートして利用します。
+実装例は以下の通りです。
+
+```ts title="メッセージ利用例"
+
+
+// テンプレート構文上で利用する場合
+
+
+ {{ t('errorOccurred') }}
+
+
+```
+
+メッセージ関数 `t()` を利用してメッセージを取得します。
+メッセージ関数 `t()` の引数には、 JSON ファイルのメッセージコードを指定してメッセージ本体を呼び出します。
diff --git a/documents/contents/guidebooks/how-to-develop/vue-js/optional-packages.md b/documents/contents/guidebooks/how-to-develop/vue-js/optional-packages.md
index d02dc79c1..82e8ee85c 100644
--- a/documents/contents/guidebooks/how-to-develop/vue-js/optional-packages.md
+++ b/documents/contents/guidebooks/how-to-develop/vue-js/optional-packages.md
@@ -94,3 +94,7 @@ description: Vue.js を用いた クライアントサイドアプリケーシ
- [yup :material-open-in-new:](https://github.com/jquense/yup){ target=_blank }
JavaScript でフォームのバリデーションルールを宣言的に記述できるライブラリ([インストール方法](input-validation.md#install-packages))
+
+- [Vue I18n :material-open-in-new:](https://vue-i18n.intlify.dev/){ target=_blank }
+
+ Vue.js アプリケーションでメッセージを外部ファイルで一元管理したり、多言語対応するためのライブラリ([インストール方法](input-validation.md#install-packages))
diff --git a/documents/contents/images/app-architecture/client-side-rendering/error-message-delivery-dark.png b/documents/contents/images/app-architecture/client-side-rendering/error-message-delivery-dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..111f7b4a579d5f17d6889bef2118cf0461d909b8
GIT binary patch
literal 240913
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