Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

メッセージ管理機能方針の策定 #1526

Merged
merged 58 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
50d471e
メッセージプロパティを各サブプロジェクトで管理するよう変更する
rnakagawa16 Oct 4, 2024
6213333
使用していないimportの削除
rnakagawa16 Oct 7, 2024
54aec8d
メッセージコードをフロントエンドに合わせて頭文字を小文字にする
rnakagawa16 Oct 8, 2024
ab66a22
Merge branch 'main' into feature/メッセージ管理機能を調査する
rnakagawa16 Oct 22, 2024
9439ff4
Merge branch 'main' into feature/メッセージ管理機能を調査する
rnakagawa16 Oct 28, 2024
acff9bc
Merge branch 'main' into feature/メッセージ管理機能を調査する
rnakagawa16 Oct 30, 2024
6c18817
フロントエンド側のメッセージ管理機能実装
rnakagawa16 Nov 1, 2024
a6e0532
バックエンド側のエラーメッセージ出力を実装
rnakagawa16 Nov 7, 2024
67dd8a3
Merge branch 'main' into feature/メッセージ管理機能を調査する
rnakagawa16 Nov 7, 2024
bcd5f2a
フロントエンド側のメッセージ管理機能の実装
rnakagawa16 Nov 14, 2024
f2e4b5c
起動方法の修正
rnakagawa16 Nov 14, 2024
3d04850
テスト時の警告解除
rnakagawa16 Nov 14, 2024
6a1be16
Merge branch 'main' into feature/メッセージ管理機能の実装
rnakagawa16 Nov 14, 2024
7b01f87
type-checkの警告対応
rnakagawa16 Nov 15, 2024
7938a9c
typecheckの警告回避と日英対応のメッセージ作成
rnakagawa16 Nov 18, 2024
9455d58
Merge branch 'main' into feature/メッセージ管理機能の実装
rnakagawa16 Nov 18, 2024
cd8067d
エラーハンドリング機能の修正
rnakagawa16 Nov 20, 2024
abe1619
if文の修正
rnakagawa16 Nov 21, 2024
b8e0a1b
ドキュメントの追加
rnakagawa16 Nov 25, 2024
a38a72b
Merge branch 'main' into feature/メッセージ管理機能の実装
rnakagawa16 Nov 26, 2024
828bc5d
ドキュメントの追加
rnakagawa16 Nov 28, 2024
1c8ea82
エラーメッセージに関する記載の修正
rnakagawa16 Nov 28, 2024
6d2a717
入力値検証のドキュメント修正
rnakagawa16 Nov 28, 2024
4607051
ブラウザーの言語設定の取得方法修正
rnakagawa16 Nov 29, 2024
8ccc093
ドキュメント指摘事項の修正
rnakagawa16 Nov 29, 2024
952a95c
クリップボード機能の修正
rnakagawa16 Nov 29, 2024
508e565
textlintエラーへの対応
rnakagawa16 Nov 29, 2024
e9eb082
入力値検証に関するドキュメントの修正
rnakagawa16 Nov 29, 2024
b961ee8
ドキュメント指摘事項の修正
rnakagawa16 Dec 2, 2024
daaed4a
ドキュメントのimport文の削除
rnakagawa16 Dec 2, 2024
d389691
起動方法の修正
rnakagawa16 Dec 2, 2024
03b8c60
ドキュメントのアプリ起動方法を記載
rnakagawa16 Dec 2, 2024
64513b3
冗長な文章を修正
rnakagawa16 Dec 2, 2024
3cf9605
ハイライトを修正
rnakagawa16 Dec 2, 2024
f119ff4
指摘事項と軽微なドキュメントの修正
rnakagawa16 Dec 2, 2024
b9ee648
変数名の修正
rnakagawa16 Dec 2, 2024
5370083
Merge branch 'main' into feature/メッセージ管理機能の実装
rnakagawa16 Dec 12, 2024
314d1f8
指摘事項の対応
rnakagawa16 Dec 13, 2024
e8be440
リンクの修正
rnakagawa16 Dec 13, 2024
97bb624
アセットサポートのエラーメッセージをプロパティファイルに設定する
rnakagawa16 Dec 13, 2024
7f868b6
OpenAPI 仕様書について ProblemDetailsを考慮した形に修正
rnakagawa16 Dec 17, 2024
01c10de
ProblemDetailの出力方法を修正
rnakagawa16 Dec 17, 2024
110b7de
プロパティに関するコメントを追加
rnakagawa16 Dec 17, 2024
e3fafbd
指摘事項の修正
rnakagawa16 Dec 19, 2024
2421187
メッセージ管理機能をADB2Cプロジェクトに導入
rnakagawa16 Dec 19, 2024
aa62157
Content-Typeをapplication/problem+jsonに修正
rnakagawa16 Dec 19, 2024
77cfb3d
ADB2CプロジェクトにProblemDetailsの対応を反映
rnakagawa16 Dec 19, 2024
6efb080
カスタムエラーハンドラーの修正
rnakagawa16 Dec 20, 2024
612c71a
responseにexceptionIdが含まれるかどうかで処理を分岐するよう修正
rnakagawa16 Dec 23, 2024
bffb4c6
定数クラスの修正
rnakagawa16 Dec 24, 2024
0589a27
DIによるメッセージ取得に変更
rnakagawa16 Dec 24, 2024
f3c8dd9
ドキュメントの修正とADB2Cサンプルに対する修正
rnakagawa16 Dec 24, 2024
b27aa5f
クラス名の修正
rnakagawa16 Dec 24, 2024
580faa5
textlint 対応
rnakagawa16 Dec 24, 2024
0d969df
Merge branch 'main' into feature/メッセージ管理機能を調査する
rnakagawa16 Dec 26, 2024
def04ff
競合による修正
rnakagawa16 Dec 26, 2024
879d292
競合箇所の修正
rnakagawa16 Dec 26, 2024
5a93412
重複するコメントの削除
rnakagawa16 Dec 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,19 @@ ProblemDetails は、 HTTP API のエラーレスポンスを標準化するた
| 問題が発生したリソースの URI | instance | 任意 | 問題の発生場所を示す URI です。リクエスト先と異なるリソースが問題の発生したリソースである場合、実装の詳細やデータなどの内部情報が漏洩する可能性があるため、追加には注意が必要です。 |
| 任意のパラメータ | | 任意 | 拡張メンバーです。必要に応じて ProblemDetails のプロパティを拡張する場合に利用します。 |

AlesInfiny Maia OSS Edition では、上記のプロパティに加えて拡張メンバーとして以下を定義しています。
ProblemDetails のレスポンスに含める各プロパティは以下のような観点をもとに取捨選択します。

- 環境による判断

- 本番環境の場合には、ユーザーが見て管理者に伝えるための情報のみをプロパティに含めるべきです。
- 開発環境の場合には、開発者がデバッグやテストなどの作業で確認すべき情報を含めるべきです。

- API の用途による判断

- 外部公開 API の場合には、セキュリティやプライバシーを考慮し、必要最低限の情報を提供するようにプロパティを設定します。
- 内部 API の場合には、画面に対応したエラーレスポンスとして含めるべきプロパティを設定します。

また、 AlesInfiny Maia OSS Edition では、フロントエンド側で管理しているメッセージを取得するために以下の拡張メンバーを追加で定義しています。

- exceptionId

Expand All @@ -139,7 +151,7 @@ AlesInfiny Maia OSS Edition では、上記のプロパティに加えて拡張

```json title="開発環境の場合のエラーレスポンス"
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Type: application/problem+json; charset=utf-8

{
"type": "https://hoge.com/error/catalogItemIdDoesNotExistInBasket",
Expand All @@ -153,7 +165,7 @@ Content-Type: application/json; charset=utf-8

```json title="本番環境の場合のエラーレスポンス"
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Type: application/problem+json; charset=utf-8

{
"type": "https://hoge.com/error/catalogItemIdDoesNotExistInBasket",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ JSON ファイルでは、以下のようにメッセージ文字列を識別す

OpenAPI 仕様書などの各 JSON ファイルと命名規則を統一するため、メッセージコードをキャメルケースとします。
それに伴い、フロントエンド側に合わせてバックエンドのプロパティファイルのメッセージコードもキャメルケースで記載します。
バックエンドのプロパティファイルの設定例は、[こちら](../global-function/message-management-policy.md#message-codes-definition) を確認してください。
バックエンドのプロパティファイルの設定例は、[こちら](../../overview/java-application-processing-system/message-management-policy.md#property-file-management) を確認してください。

### エラーメッセージ内のパラメータ {#parameter-of-error-messages}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ description: アプリケーションの形態によらず、 Java アプリケ

プロパティファイルでは、以下のようにメッセージ文字列を識別するメッセージコードとメッセージ文字列本体をペアで管理します。

```properties title="message.properties の例"
```properties title="messages.properties の例"
errorOccurred=エラーが発生しました。
...
```
Expand All @@ -30,16 +30,16 @@ errorOccurred=エラーが発生しました。

## メッセージの管理単位 {#management-unit}

以下のように、ビジネスロジックで発生する業務メッセージと共通処理として発生する共通メッセージを分割して各サブプロジェクトで管理します
以下のように、ビジネスロジックで利用する業務メッセージと共通処理として利用する共通メッセージを分割して各サブプロジェクトで管理します

```terminal linenums="0"
root/ ------------------------------------------ root フォルダー
├ application-core/src/main/resource
│ └ applicationcore --------------------------- 業務メッセージのプロパティファイルを一括管理するフォルダー
tsuna-can-se marked this conversation as resolved.
Show resolved Hide resolved
│ └ message.properties --------------------- 業務メッセージのプロパティファイル
│ └ messages.properties --------------------- 業務メッセージのプロパティファイル
└ system-common/src/main/resource
└ systemcommon ------------------------------ 共通メッセージのプロパティファイルを一括管理するフォルダー
message.properties --------------------- 共通メッセージのプロパティファイル
messages.properties --------------------- 共通メッセージのプロパティファイル
```

業務メッセージと共通メッセージとして格納するメッセージの例は以下の通りです。
Expand All @@ -63,14 +63,14 @@ root/ ------------------------------------------ root フォルダー
root/ ------------------------------------------ root フォルダー
├ application-core/src/main/resource
│ └ applicationcore --------------------------- 業務メッセージのプロパティファイルを一括管理するフォルダー
│ ├ message_en.properties ------------------ 業務メッセージのプロパティファイル(英語)
│ └ message_ja.properties ------------------ 業務メッセージのプロパティファイル(日本語)
│ ├ messages_en.properties ------------------ 業務メッセージのプロパティファイル(英語)
│ └ messages_ja.properties ------------------ 業務メッセージのプロパティファイル(日本語)
└ system-common/src/main/resource
└ systemcommon ------------------------------ 共通メッセージのプロパティファイルを一括管理するフォルダー
message_en.properties ------------------ 共通メッセージのプロパティファイル(英語)
message_ja.properties ------------------ 共通メッセージのプロパティファイル(日本語)
messages_en.properties ------------------ 共通メッセージのプロパティファイル(英語)
messages_ja.properties ------------------ 共通メッセージのプロパティファイル(日本語)
```

アプリケーション起動時に使用するメッセージファイルを切り替えることで、開発者に応じた言語を設定します。

メッセージ管理方針に従った機能の実装方法などの詳細については、[こちら](../../../guidebooks/how-to-develop/java/common-project-settings.md) を確認してください。
メッセージ管理方針に従った機能の実装方法などの詳細については、[こちら](../../../guidebooks/how-to-develop/java/sub-project-settings/message-management.md) を確認してください。
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,7 @@ application-core プロジェクトの `src` 以下にある、 `ApplicationCore
enabled = true
}
```

## メッセージ管理の設定 {#message-management-settings}

application-core プロジェクトで管理する業務メッセージの設定方法については、[こちら](./message-management.md) を参照してください。
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ description: バックエンドで動作する Java アプリケーションの
1. [プラグイン、依存ライブラリのバージョン定義一元化](./project-version-control.md)

プラグイン、依存ライブラリのバージョン定義を一元的に管理する方法について解説します。

1. [メッセージ管理機能の設定](./message-management.md)

マルチプロジェクト構成におけるメッセージ管理の設定方法について解説します。
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
title: Java 編
description: バックエンドで動作する Java アプリケーションの 開発手順を解説します。
---

<!-- cspell:ignore applicationcore systemcommon -->

# メッセージ管理機能の設定 {#top}

バックエンドのメッセージ管理方針に関するアーキテクチャについては、[こちら](../../../../app-architecture/overview/java-application-processing-system/message-management-policy.md) をご確認ください。

## 設定方法 {#settings}

本設定で利用するフォルダーの構成は以下の通りです。

```terminal linenums="0"
root/ ------------------------------------------ root フォルダー
├ application-core/src/main/resource
│ └ applicationcore --------------------------- 業務メッセージのプロパティファイルを一元管理するフォルダー
│ └ messages.properties --------------------- 業務メッセージのプロパティファイル
└ system-common/src/main/resource
└ systemcommon ------------------------------ 共通メッセージのプロパティファイルを一元管理するフォルダー
└ messages.properties --------------------- 共通メッセージのプロパティファイル
```

### プロパティファイルの作成 {#creating-property-file}

メッセージに関するプロパティファイルは各サブプロジェクトの `/src/main/resource/<サブプロジェクト名>` フォルダーに集約します。
以下のように、メッセージ本体を格納するプロパティファイルを作成します。

```properties title="message.properties"
systemError=想定外のシステムエラーが発生しました
businessError=想定外の業務エラーが発生しました
```

### プロパティファイルの読込 {#reading-property-files}

以下のように、 web プロジェクトなどエントリーポイントとなるサブプロジェクトの application.properties にプロパティファイルを読み込む設定を記載します。

``` properties title="application.properties"
spring.messages.basename=applicationcore.messages,systemcommon.messages
tsuna-can-se marked this conversation as resolved.
Show resolved Hide resolved
```

読み込むプロパティファイルは `src/main/resource` 配下の `<フォルダー名>.<ファイル名>` で指定します。
プロパティファイルが複数ある場合は、ファイルの間をカンマで区切ります。

### メッセージの取得 {#getting-messages}

読み込んだプロパティファイルのメッセージを取得するためには、 [`MessageSource` :material-open-in-new:](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/context/MessageSource.html){ target=_blank } クラスを利用します。

以下は、プロパティファイルからメッセージを取得し、ログに出力するためのエラーメッセージを整形する `ErrorMessageBuilder` クラスの例です。

```java title="ErrorMessageBuilder.java" hl_lines="5 14"
@Getter
@AllArgsConstructor
public class ErrorMessageBuilder {

private static final MessageSource messageSource = (MessageSource) ApplicationContextWrapper.getBean(MessageSource.class);
TakashiOhkubo marked this conversation as resolved.
Show resolved Hide resolved

private Exception ex;
private String exceptionId;
private String[] logMessageValue;
private String[] frontMessageValue;

public String createLogMessageStackTrace() {
StringBuilder builder = new StringBuilder();
String exceptionMessage = messageSource.getMessage(exceptionId, logMessageValue, Locale.getDefault());
builder.append(exceptionId).append(" ").append(exceptionMessage).append(SystemPropertyConstants.LINE_SEPARATOR);
StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
builder.append(writer.getBuffer().toString());
return builder.toString();
}
}
```

<!-- textlint-disable ja-technical-writing/sentence-length -->
また、 `#!java @Service` や `#!java @Controller` 、 `#!java @Component` といった Bean 登録されたクラス内で `MessageSource` を利用する場合は、 `#!java @Autowired` による DI で実装します。
<!-- textlint-enable ja-technical-writing/sentence-length -->

以下は、プロパティファイルからエラーレスポンスに含めるメッセージを整形する `ProblemDetailsFactory.java` クラスの例です。

```java title="ProblemDetailsFactory.java" hl_lines="4 5 11"
@Component
public class ProblemDetailsFactory {

@Autowired
private MessageSource messages;

public ProblemDetail createProblemDetail(ErrorMessageBuilder errorBuilder, String titleId, HttpStatus status) {

ProblemDetail problemDetail = ProblemDetail.forStatus(status);

problemDetail.setTitle(messages.getMessage(titleId, new String[] {}, Locale.getDefault()));

...
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,7 @@ system-common プロジェクトの `src` 以下にある、 `SystemCommonApplic
enabled = true
}
```

## メッセージ管理の設定 {#message-management-settings}

system-common プロジェクトで管理する共通メッセージの設定方法については、[こちら](./message-management.md) を参照してください。
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,7 @@ build.dependsOn("generateOpenApiDocs")
## CORS (クロスオリジンリソース共有)環境の設定 {#cors-environment}

Web API を公開するオリジンと、呼び出し元となるクライアントスクリプトを公開するオリジンが異なる場合(クロスオリジン)の設定は、[こちら](../../cors/index.md) を参照してください。

## メッセージ読込に関する設定 {#message-reading-settings}

他サブプロジェクトで管理されているメッセージを読み込む場合の設定は、[こちら](./message-management.md) を参照してください。
1 change: 1 addition & 0 deletions documents/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ nav:
- batch プロジェクトの設定: guidebooks/how-to-develop/java/sub-project-settings/batch-project-settings.md
- system-common プロジェクトの設定: guidebooks/how-to-develop/java/sub-project-settings/system-common-project-settings.md
- プラグイン、依存ライブラリのバージョン定義一元化: guidebooks/how-to-develop/java/sub-project-settings/project-version-control.md
- メッセージ管理機能の設定: guidebooks/how-to-develop/java/sub-project-settings/message-management.md
- Vue.js 編:
- guidebooks/how-to-develop/vue-js/index.md
- 事前準備: guidebooks/how-to-develop/vue-js/preparation.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"console": "internalConsole",
"mainClass": "com.dressca.web.WebApplication",
"projectName": "web",
"args": "",
"args": "--spring.profiles.active=local",
"envFile": "${workspaceFolder}/.env"
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
"description": "成功."
},
"401": {
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetail"
}
}
},
"description": "未認証エラー."
}
},
Expand All @@ -77,27 +84,56 @@
},
"components": {
"schemas": {
"TimeResponse": {
"ProblemDetail": {
"type": "object",
"properties": {
"serverTime": {
"detail": {
"type": "string"
},
"instance": {
"type": "string",
"format": "uri"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "object"
}
},
"status": {
"type": "integer",
"format": "int32"
},
"title": {
"type": "string"
},
"type": {
"type": "string",
"format": "uri"
}
},
}
},
"TimeResponse": {
"required": [
"serverTime"
]
],
"type": "object",
"properties": {
"serverTime": {
"type": "string"
}
}
},
"UserResponse": {
"required": [
"userId"
],
"type": "object",
"properties": {
"userId": {
"type": "string"
}
},
"required": [
"userId"
]
}
}
},
"securitySchemes": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.dressca.systemcommon.constant;

/**
* 例外ID用定数クラス。
*/
public class CommonExceptionIdConstants {
/** 想定外のシステムエラーが発生しました。 */
public static final String E_SYSTEM = "systemError";

/** 想定外の業務エラーが発生しました。 */
public static final String E_BUSINESS = "businessError";

/** 未認証のエラーが発生しました。 */
public static final String E_UNAUTHORIZED = "unauthorizedError";
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
spring.messages.basename=messages
spring.messages.basename=systemcommon.messages
spring.messages.encoding=UTF-8

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
systemError=想定外のシステムエラーが発生しました。
businessError=想定外の業務エラーが発生しました。
unauthorizedError=未認証のエラーが発生しました。
7 changes: 7 additions & 0 deletions samples/azure-ad-b2c-sample/auth-backend/web/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,12 @@ openApi {
tasks.named('test') {
useJUnitPlatform()
}
tasks.register('bootRunDev', org.springframework.boot.gradle.tasks.run.BootRun){
group = 'application'
description = 'Runs this project as a Spring Boot Application using local profile.'
args = ["--spring.profiles.active=local"]
main = 'com.dressca.web.WebApplication'
classpath = sourceSets.main.runtimeClasspath
}

build.dependsOn("generateOpenApiDocs")
Loading
Loading