OutSystemsの例外処理の仕組みは、他のプログラミング言語と概ね同じなんですが、奇妙な成約がいくつかあります。定義したExceptionをPublicにできないとか、例外自体から取得できる情報がText型1つ(ExceptionMessageです)であるとか。
そうした成約の一つとして、Client Action利用時に、汎用的なUser Exceptionではの例外ハンドルができないという問題に遭遇したのでメモしておきます。
環境
Personal Environment(Version 11.9.0 (Build 16900))
Service Studio (Version 11.8.12)
テスト設定
SampleUserExceptionを定義。OutSystemsでは、任意に定義するExceptionの型はUser Exceptionの下に作られます。
Image may be NSFW.
Clik here to view.
この場合、SampleUserExceptionは汎用的なUser Exceptionとしても処理できるはず。
公式ドキュメント:例外を処理するによると、以下のように記述されているため。
作成したUser Exceptionは、汎用的なUser Exceptionの「子ノード」となります。つまり、汎用的なUser Exceptionハンドラは、指定したUser Exceptionの前にフローで発生したあらゆる独自のUser Exceptionを処理します。
Client ActionではUserExceptionでハンドルできない
定義した例外をThrowするだけのClient Actionを定義します。
Image may be NSFW.
Clik here to view.
例外はSampleUserException>UserException>AllExceptionの優先順位でハンドルされるはず。
左から順にDisable Elementsで無効化しながら実行してちゃんとハンドルされるか確認してみます。
すると、SampleUserExceptionを無効化した状態で、User Exceptionでなく、All Exceptionでハンドルされました。
- 上の状態でActionを実行する → SampleUserExceptionのException Handlerで処理される
- SampleUserExceptionをDisableしてActionを実行する → AllExceptionsのException Handlerで処理される
- SampleUserExceptionとUserExceptionをDisableしてActionを実行 → AllExceptionsのException Handlerで処理される
と、いうわけで、Client ActionではUser Exceptionを使っての例外処理ができないようです。
ドキュメントでは、根拠が見つからないのですが……。
Server Action内での例外処理ではUserExceptionでハンドルできる(想定通り)
Client でのテストと同じ構成でActionを作り、Disableしながらテスト。
こちらは2. の段階で、UserExceptionのException Handlerで処理できます。
UserExceptionで処理したい問題
なぜ、UserExceptionで処理したいかというと、独自に定義した例外については、JSONを介して構造データ(ログシーケンスや発生場所などの情報を詰める)を渡したいから。
1. 独自定義例外用のエラーメッセージStructureを定義
2. 例外を発生させるときにエラーメッセージStructureを設定
3. StructureをSerializeしてJSONに変換
4. JSONをExceptionMessageに設定して例外を発生させる
ということをやるため。
OutSystemsの例外は情報としてはText型のExceptionMessageしか渡せないため、例外発生時の共通処理を書くときに不便なので本当はこういうことがやりたいのです。
代替案
↑の処理は、各所で発生した例外を一箇所(おそらくGlobal Exception Handler)で統一した処理したいということです。
「例外はロジック分岐のために使わず、真に例外的な状況でのみ使おう」という指針に従うなら、具体的なUserExceptionを発生させようとしているActionで処理を見直し、できるだけ出力パラメータにエラーを返し、例外を発生しないようにすることでしょうか。