[OutSystems]サーバー側で発生したExceptionがどのようにクライアント側に渡るのか

OutSystemsでは、Client Actionからサーバー側の処理を呼ぶと、（当然ながら）通信が発生する。サーバー側ロジックからクライアント側ロジックにExceptionが伝わっているので、通信の中でExceptionがどう表現されているかを確認してみた。

# 修正履歴
- 2024/05/28 ODCの場合のレスポンスとステータスコードを追記

# 環境
Personal Environment(Version 11.17.0 (Build 36291))
Service Studio(Version 11.53.13)

# (2024/05/28 追記）ODCの場合
通信に乗っている例外情報はほぼ同じ。ODCの場合、エラーコード（2024/05時点では定義のリストはないはず）がエラー種別ごとに定義されているようなので記述されている。また、ODC PortalでのTraceを特定できるtraceId項目もある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/58db82dd-f2d0-157f-f1a2-a764e08d62b1.png)

Status Codeは250だった。200番台なので成功の扱い。

# サンプルモジュール
[Forgeコンポーネント](https://www.outsystems.com/forge/component-overview/7086/housesoftsamplereactive)のV1.0.11。
MainFlow > Exception Screenの「②サーバーで発生した例外をClientで補足する」

# 結果のまとめ
## 通信の内容
Client Actionから呼び出したサーバー側ロジックで発生したExceptionは、HTTP通信のレスポンスとして、以下の形式となる（画像はChromeのデベロッパーツールでみた結果）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/41de2673-30d9-f006-334b-6e20ef0aa2ff.png)

HTTPレスポンスのJSON中のexceptionプロパティにExceptionの中身が入る。
- exception
    - message: Exceptionの「Exception Messageプロパティ」に渡したメッセージ
    - name: （ドキュメントでは確認できないが見る限り）例外の種類。Exception Handlerで補足できるExceptionの種類に対応している。これがUserExceptionであれば、Exception HandlerのExceptionプロパティを「UserException」にすると補足できる
    - specificType: 基本的に「モジュール名.Exception名」

## 
| テストパターン | nameプロパティ | specificTypeプロパティ |
|:-:|:-:|:-:|
| Server Action [^1] | UserException  | モジュール名.Exception名  |
| Service Action  | UserException  | UserException  |
| Extension  | ServerException  | OutSystems.NssExtension名.例外class名  |
| Expose REST API  | ServerException  | System.Exception  |
| Server ActionでOutSystems提供の例外をRaise  | InvalidLoginException [^2]  | ""  |

[^1]: 同じモジュールにある場合、外部モジュールにある場合で同じ結果
[^2]: Raiseした例外そのもの。ここではSecurity Exceptionの下にあるInvalid LoginをRaiseした場合の結果を示している

# 検証用実装
Reactive Web Appの以下のようなClient Actionから、（必ず例外をRaiseする）各種サーバー側処理を呼び出し、どの種類の例外にHandleされるかと、通信内容を確認した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/faaa458a-6d76-fadb-8c81-a1727b575d3f.png)

## Server Action
呼び出すActionは以下のとおり。実行すると、定義したUser Exception（Sample Exception）を必ずRaiseする（Exception Message: "Exception2_1"）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/34749ed0-1d31-cff4-fb5a-1d1300139149.png)

この場合、
- SampleExceptionとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "Exception2_1"
    - name: "UserException"
    - specificType: "HousesoftSampleReactive.SampleException"

### 外部モジュールのServer Actionで例外が起きたとき
呼び出す先のServer Actionが別のモジュールにあった場合に、通信内容に変化がないかを確認してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/64aae9ca-1114-271b-4feb-2b93f282b54f.png)

- UserExceptionとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "Exception2_1_Producer"
    - name: "UserException"
    - specificType: "HousesoftSampleReactiveProducer.SampleExceptionInProducer"

### OutSystems提供のException
今度は、同じモジュールのServer Actionから、独自に定義したExceptionでなくOutSystemsに元々備わっていたExceptionをRaiseしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/fe8579df-5030-6ab1-25d3-d8f94037cdf1.png)

- Invalid LoginとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "Exception2_1_ProvidedException"
    - name: "InvalidLoginException"
    - specificType: ""

# Service Action
外部モジュールにあるService Actionで例外が発生した場合。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/cfbfa7ae-8e9a-b010-965c-ad63ce1f4f0f.png)

- User ExceptionとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "Exception2_2"
    - name: "UserException"
    - specificType: "UserException"

# Extension
Client ActionからExtensionに定義したServer Actionを呼び、その中でC#の例外classをthrowした場合。当然、OutSystemsで定義したExceptionとは別のものなので、どういう結果になるか。

- All ExceptionとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "Actionメソッドから直接例外をthrowする"
    - name: "ServerException"
    - specificType: "OutSystems.NssHousesoftSampleReactiveExtension.MyException"

# Expose REST
絶対に例外を投げるExpose REST APIを作成し、そのAPIをConsumeし、さらにConsumeしたものをClient Actionから読んで結果を確認する。

- All ExceptionとしてHandleされる
- 通信レスポンスのexceptionプロパティの例
    - message: "500 Internal Server Error"
    - name: "ServerException"
    - specificType: "System.Exception"