omnistudio-callable-apex-generate について
Salesforce Industries Common Core の callable Apex 実装を作成・レビューするスキルです。System.Callable のアクション振り分け、安全な入出力契約、旧 Vlocity Open Interface 拡張からの移行に対応します。
主な機能
- 01System.Callable クラスの生成
- 02アクション契約の定義と検証
- 03共有設定と CRUD/FLS の確認
- 04旧 Open Interface 実装の移行
- 05callable コードの評価とテスト
活用シーン
- 01OmniStudio から呼び出すアクションの追加
- 02callable のセキュリティと一括処理のレビュー
- 03VlocityOpenInterface2 から System.Callable への移行
- 04対応・非対応アクションのテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill omnistudio-callable-apex-generateインストール後、Claude Code で/omnistudio-callable-apex-generateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdassets/pattern_callable_openinterface.clspattern_callable_vanilla.clspattern_migration.clspattern_openinterface.clspattern_test_class.clsexamples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.clsIndustries_QuoteByProductCallableTest.clsIndustriesCallableException.clsTRANSCRIPT.mdexamples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.clsMyCustomCallable.clsMyCustomCallableTest.clsMyCustomRemoteClass.clsTRANSCRIPT.mdexamples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.clsMyCustomCallable.clsMyCustomCallableTest.clsMyCustomClass.clsTRANSCRIPT.md詳細
omnistudio-callable-apex-generate:Salesforce Industries Common Core の Callable Apex
Salesforce Industries Common Core の Callable Apex 実装に特化したツールです。OmniStudio と Industries の拡張ポイントに適切に統合できる、安全で決定論的かつ設定可能な Apex を生成します。
対象範囲
- 対象範囲内:Industries の拡張ポイント向け
System.Callableクラスの作成、正確性とリスクの観点からの Callable 実装のレビュー、VlocityOpenInterface/VlocityOpenInterface2からSystem.Callableへの移行、120 点満点のスコアリングと検証 - 対象範囲外:Callable インターフェースを実装しない汎用 Apex クラス(
platform-apex-generateを使用)、Integration Procedure の構築(omnistudio-integration-procedure-generateを使用)、OmniScript の作成(omnistudio-omniscript-generateを使用)、Apex クラスのデプロイ(platform-metadata-deployを使用)
主な役割
- Callable の生成:安全なアクションディスパッチを備えた
System.Callableクラスを構築します - Callable のレビュー:既存の Callable 実装を監査し、正確性とリスクを確認します
- 検証とスコアリング:120 点満点の評価基準に照らして評価します
- Industries との適合性:OmniStudio/Industries の拡張ポイントとの互換性を確保します
ワークフロー(4 フェーズのパターン)
フェーズ 1:要件の収集
次の情報を確認します。
- エントリポイント(OmniScript、Integration Procedure、DataRaptor、またはその他の Industries フック)
- アクション名(
callに渡される文字列) - 入出力の契約(必須キー、型、レスポンス形式)
- データアクセスの要件(オブジェクト/項目、CRUD/FLS(作成/参照/更新/削除および項目レベルセキュリティ)のルール)
- 副作用(DML、コールアウト、非同期処理の要件)
次に、以下を行います。
- 既存の Callable クラスを検索します:
Glob: **/*Callable*.cls - Industries の拡張機能で使われている共有ユーティリティや基底クラスを特定します
- タスクリストを作成します
フェーズ 2:設計と契約の定義
Callable の契約を定義します。
- アクション一覧(明示的で、バージョン管理された文字列)
- 入力スキーマ(必須キーと型)
- 出力スキーマ(一貫したレスポンスエンベロープ)
推奨されるレスポンスエンベロープ:
{
"success": true|false,
"data": {...},
"errors": [ { "code": "...", "message": "..." } ]
}
アクションディスパッチのルール:
switch on actionを使用しますdefaultケースでは、型付き例外をスローします- 動的メソッド呼び出しやリフレクションは使用しません
VlocityOpenInterface / VlocityOpenInterface2 の契約マッピング:
従来の Open Interface 拡張機能(または Callable と Open Interface の両方をサポートする場合)の設計では、次のシグネチャをマッピングします。
invokeMethod(String methodName, Map<String, Object> inputMap, Map<String, Object> outputMap, Map<String, Object> options)
| パラメーター | 役割 | Callable での対応 |
|---|---|---|
methodName | アクションの選択子(action と同じ意味) | call(action, args) の action |
inputMap | 主な入力データ(必須キー、型) | args.get('inputMap') |
outputMap | 結果を書き込む変更可能なマップ(参照渡しで出力) | 戻り値。Callable では代わりにエンベロープを返します |
options | 追加のコンテキスト(親 DataRaptor/OmniScript のコンテキスト、呼び出しメタデータ) | args.get('options') |
Open Interface の契約に関する設計ルール:
inputMapとoptionsを組み合わせて入力スキーマとして扱います- アクションごとに、
outputMapに書き込む必要があるキーを(成功時とエラー時の両方について)定義します methodNameの文字列を維持し、Callable のaction文字列と一致させます- アクションごとに、
optionsが必須、任意、または未使用のいずれであるかを記載します
フェーズ 3:実装パターン
Vanilla System.Callable(フラットな引数、Open Interface との結合なし):
生成前に assets/pattern_callable_vanilla.cls をお読みください。呼び出し元がフラットな引数を渡し、VlocityOpenInterface との統合が不要な場合に使用します。
Callable のひな形(VlocityOpenInterface と同じ入力):
生成前に assets/pattern_callable_openinterface.cls をお読みください。Open Interface と統合する場合、または呼び出し元がその構造を渡す場合は、args 内の inputMap と options のキーを使用します。
入力形式:呼び出し元は args を { 'inputMap' => Map<String, Object>, 'options' => Map<String, Object> } として渡します。フラットな引数を渡す呼び出し元との後方互換性を保つため、args に 'inputMap' がない場合は、args 自体を inputMap として扱い、options には空のマップを使用します。
実装ルール:
call()は薄く保ち、プライベートメソッドまたはサービスクラスに処理を委譲します- 入力の型を早い段階で検証し、変換します(null セーフにします)
- CRUD/FLS(作成/読み取り/更新/削除と項目レベルセキュリティ)および共有設定(
with sharing、Security.stripInaccessible())を適用します argsにレコードコレクションが含まれる場合は、一括処理に対応させます- 適切な場合は、SOQL に
WITH USER_MODEを使用します - 名前空間の処理:
System.Callableは標準インターフェースであり、名前空間プレフィックスは不要です。omnistudio.VlocityOpenInterface2は管理パッケージの名前空間omnistudioを使用するため、必ず名前空間を指定します。Callable クラスを名前空間付きの管理パッケージにデプロイする場合は、ユーザーに名前空間プレフィックスを確認し、カスタムクラス名に適用します(例:myns__Industries_XxxCallable)
VlocityOpenInterface/VlocityOpenInterface2 の実装:
omnistudio.VlocityOpenInterface または omnistudio.VlocityOpenInterface2 を実装する場合は、次のシグネチャを使用します。
global Boolean invokeMethod(String methodName, Map<String, Object> inputMap,
Map<String, Object> outputMap, Map<String, Object> options)
生成前に assets/pattern_openinterface.cls をお読みください。switch on によるディスパッチと outputMap の契約を含む、VlocityOpenInterface2 の完全なひな形です。
Open Interface の実装ルール:
putAll()または個別のput()呼び出しを使用して、結果をoutputMapに書き込みます。invokeMethodからエンベロープを返さないでください- 成功時は
true、サポートされていないアクションまたは失敗時はfalseを返します - Callable と同じ内部プライベートメソッドを使用し、同じ
inputMapとoptionsパラメーターを渡します。異なるのはエントリーポイントのみです - 一貫性を保つため、同じエンベロープ形式(
success、data、errors)でoutputMapを設定します
Callable と Open Interface は同じ入力(inputMap、options)を受け取り、共通ロジックについては同一のプライベートメソッドシグネチャに処理を委譲します。
フェーズ 4:テストと検証
最低限必要なテスト:
- 正常系:サポートされているアクションが正常に実行される
- 異常系:サポートされていないアクションで想定された例外がスローされる
- 契約:入力が不足または無効な場合に、エラーエンベロープが返される
- 一括処理:リスト入力を処理し、制限に達しない
テスト生成前に assets/pattern_test_class.cls をお読みください。正常系、異常系、契約、一括処理、null の引数のケースを含む完全なテストクラスのひな形です。
VlocityOpenInterface から System.Callable への移行
Industries の拡張機能を最新化する際は、VlocityOpenInterface または
VlocityOpenInterface2 の実装を System.Callable に移行し、
アクションの契約を維持します。
ガイダンス:
methodNameのアクション名を、call()内のaction文字列として維持しますinputMapとoptionsをargs内のキーとして渡します:{ 'inputMap' => inputMap, 'options' => options }outMapを変更する代わりに、一貫したレスポンスエンベロープを返しますcall()は薄く保ち、(inputMap, options)シグネチャを持つ同じ内部メソッドに処理を委譲します- 各アクションとサポートされていないアクションのテストを追加します
移行を始める前に assets/pattern_migration.cls をお読みください。VlocityOpenInterface2 から System.Callable への移行例を、移行前後の注釈付きで示しています。
ベストプラクティス(120点満点)
| カテゴリ | 点数 | 主なルール |
|---|---|---|
| 契約とディスパッチ | 20 | アクションリストを明示すること。switch on を使用すること。アクション文字列をバージョン管理すること |
| 入力検証 | 20 | 必須キーを検証すること。型を安全に変換すること。null ガードを設けること |
| セキュリティ | 20 | with sharing を使用すること。CRUD/FLS を確認すること。Security.stripInaccessible() を使用すること |
| エラー処理 | 15 | 型付き例外を使用すること。一貫したエラーエンベロープを使用すること。空の catch を使用しないこと |
| 一括処理と制限 | 20 | ループ内で SOQL/DML を使用しないこと。リスト入力をサポートすること |
| テスト | 15 | 正常系/異常系/契約/一括処理のテストを行うこと |
| ドキュメント | 10 | クラスおよびアクションメソッドに ApexDoc(/** ... */ ブロックコメント — Salesforce Apex のドキュメント標準)を記述すること |
基準:[PASS] 90点以上(準備完了)|[REVIEW] 70~89点(要確認)|[BLOCK] 70点未満(ブロック)
ガードレール(必須)
次のいずれかが導入される場合は、作業を止めてユーザーに確認してください。
- ユーザー入力に基づく動的なメソッド実行(リフレクションは禁止)
- ループ内での SOQL/DML
- 呼び出し可能なクラスでの
without sharing - サイレントな失敗(空の catch、例外の握りつぶし)
- アクション間で一貫しないレスポンス形式
注意点
| 問題 | 解決策 |
|---|---|
呼び出し元はフラットな引数を渡すが、コードは inputMap キーを想定している | 防御的に処理してください。args に 'inputMap' キーがない場合は、args 自体を入力マップとして扱います |
call() が args に null を受け取る | キーにアクセスする前に必ず args を null チェックしてください。null の場合は空のマップを初期化します |
テストクラスで (Map<String, Object>) svc.call(...) を使用しているが、call が誤った型を返す | すべてのアクションが同じエンベロープ型(Map<String, Object>)を返すようにしてください。戻り値の型が混在すると呼び出し元で問題が発生します |
VlocityOpenInterface2 の移行により、outputMap を参照で読み取る呼び出し元が機能しなくなる | Callable への移行後、呼び出し元は outputMap を読み取るのではなく戻り値を読み取る必要があります。すべての呼び出し元を更新してください |
プロジェクトに IndustriesCallableException クラスがない | このカスタム例外は呼び出し可能なクラスと一緒にデプロイする必要があります。すべてのデプロイパッケージに含めてください |
| 組織で旧 Open Interface と新しい Callable の両方が同じアクションに接続されている | 同時に有効にするエントリポイントは1つだけにしてください。Callable が動作することを確認した後、旧インターフェースを無効にします |
よくあるアンチパターン
call()にビジネスロジックが含まれており、委譲していない- アクション名にバージョンが付いていない、またはドキュメント化されていない
- 入力マップにキーがあることを確認せずに前提としている
- 戻り値の型が混在している(Map の場合も String の場合もある)
- サポート対象外のアクションに対するテストがない
スキル間の連携
| スキル | 使用する場面 | 例 |
|---|---|---|
| platform-apex-generate | Callable の実装以外の一般的な Apex 作業 | 「Account のトリガーを作成する」 |
| platform-custom-object-generate / platform-custom-field-generate | コーディング前にオブジェクト/項目が利用可能か確認する | 「Product2 の項目を記述する」 |
| platform-metadata-deploy | Callable クラスを検証/デプロイする | 「サンドボックスにデプロイする」 |
参照スキル
次のファイルにある Apex の基本標準、テストパターン、ガードレールを使用してください。
同梱の例
- examples/Test_QuoteByProductCallable/ —
WITH USER_MODEを使用した読み取り専用クエリの例 - examples/Test_VlocityOpenInterfaceConversion/ — 旧
VlocityOpenInterfaceからの移行 - examples/Test_VlocityOpenInterface2Conversion/ —
VlocityOpenInterface2からの移行
出力要件
このスキルで作成する成果物:
<ClassName>.cls—switch on actionによるディスパッチを実装したSystem.Callable実装クラス<ClassName>Test.cls— 正常系、異常系、契約、一括処理のテストメソッドを含むテストクラスIndustriesCallableException.cls— カスタム例外クラス(プロジェクトにまだ存在しない場合)
注意事項
- 決定性があり、副作用を考慮した呼び出し可能なアクションを優先してください
- アクションの契約を安定させてください。破壊的変更には新しいアクションを導入してください
- 同期呼び出し可能な処理で時間のかかる作業を避け、必要に応じて非同期処理を使用してください
参考ファイル一覧
| ファイル | 読むタイミング |
|---|---|
assets/pattern_callable_vanilla.cls | フェーズ 3 — バニラの System.Callable スケルトン(フラットな引数、Open Interface との結合なし) |
assets/pattern_callable_openinterface.cls | フェーズ 3 — inputMap/options 引数を備えた System.Callable スケルトン(Open Interface 互換) |
assets/pattern_openinterface.cls | フェーズ 3 — switch on によるディスパッチと outputMap 契約を備えた VlocityOpenInterface2 スケルトン |
assets/pattern_test_class.cls | フェーズ 4 — テストクラスのスケルトン(成功、失敗、契約、一括処理、null 引数のケース) |
assets/pattern_migration.cls | 移行 — 移行前/移行後のパターンに注釈を付けた例(VlocityOpenInterface2 → System.Callable) |
examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.cls | フェーズ 3 — WITH USER_MODE SOQL とエラーエンベロープを備えた、完全な呼び出し可能な実装 |
examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallableTest.cls | フェーズ 4 — 成功、契約、未サポートアクションのケースを網羅した、完全なテストクラス |
examples/Test_QuoteByProductCallable/IndustriesCallableException.cls | フェーズ 3 — 未サポートアクション用のカスタム例外パターン |
examples/Test_QuoteByProductCallable/TRANSCRIPT.md | 参考 — Quote-by-Product 呼び出し可能な例の推論トランスクリプト |
examples/Test_VlocityOpenInterfaceConversion/MyCustomCallable.cls | フェーズ 3 — レガシー VlocityOpenInterface からの移行パターン |
examples/Test_VlocityOpenInterfaceConversion/MyCustomCallableTest.cls | フェーズ 4 — VlocityOpenInterface 移行例のテストクラス |
examples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.cls | フェーズ 3 — VlocityOpenInterface 変換とともにデプロイされるカスタム例外クラス |
examples/Test_VlocityOpenInterfaceConversion/MyCustomClass.cls | フェーズ 3 — 移行前の元のレガシー VlocityOpenInterface クラス |
examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md | 参考 — VlocityOpenInterface 変換の推論トランスクリプト |
examples/Test_VlocityOpenInterface2Conversion/MyCustomCallable.cls | フェーズ 3 — VlocityOpenInterface2 からの移行パターン |
examples/Test_VlocityOpenInterface2Conversion/MyCustomCallableTest.cls | フェーズ 4 — VlocityOpenInterface2 移行例のテストクラス |
examples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.cls | フェーズ 3 — VlocityOpenInterface2 変換とともにデプロイされるカスタム例外クラス |
examples/Test_VlocityOpenInterface2Conversion/MyCustomRemoteClass.cls | フェーズ 3 — VlocityOpenInterface2 移行例で使用されるリモートクラス |
examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md | 参考 — VlocityOpenInterface2 変換の推論トランスクリプト |
納品前チェックリスト
-
call()でキーにアクセスする前にargsが null でないことを確認する -
IndustriesCallableExceptionクラスがデプロイパッケージに含まれている - 該当する場合、
omnistudio.VlocityOpenInterface2に名前空間を付与する -
outputMapのキーをアクションごとに文書化する(成功時とエラー時) - 移行後の呼び出し元が、参照渡しの
outputMapではなく戻り値を読み取る