rap について
ABAP Cloudでトランザクションアプリを開発するための、ABAP RESTful Application Programming Model(RAP)の実践ガイドです。設計の選択肢、階層構成、振る舞い定義、EMLに加え、クリーンコアの制約も扱います。
主な機能
- 01RAPの手順とシナリオ選択
- 02ビジネスオブジェクトの階層設計
- 03BDLによる振る舞い定義
- 04ABPハンドラーとセーバーの指針
- 05EML操作の例
- 06ドラフトと保存シーケンスの解説
活用シーン
- 01マネージドまたはアンマネージドのRAPビジネスオブジェクト設計
- 02アクション、検証、判定の追加
- 03EMLによるRAPビジネスオブジェクトの利用
- 04RAP実装の問題調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ likweitan/ abap-skills --skill rapインストール後、Claude Code で/rapを入力して読み込まれたか確認します。
同梱ファイルreferences/eml-quick-reference.md
詳細
RAP(RESTful ABAP Programming Model)
ABAP Cloud で ABAP RESTful Application Programming Model(RAP)を使用してトランザクションアプリケーションを構築するためのガイドです。
クリーンコアのコンテキスト:RAP は ABAP Cloud 開発の主要なプログラミングモデルであり、クリーンコアレベル A に該当します。コア SAP Cloud ERP のスコープ向けにカスタム RAP ベースの Fiori アプリを作成する場合はレベル A です。また、リリース済みの拡張ポイントを使用して RAP ベースの SAP Fiori アプリを拡張する場合もレベル A です。一方、SEGW/BOPF/UI5 ベースのアプリとその拡張はレベル B です。レベル A を維持するには、RAP ハンドラーコードでリリース済み API のみを使用してください。内部オブジェクトを 1 つでも呼び出すと、アプリケーション全体がレベル C に格下げされます。各レベルの詳細については、
abap-cloudスキルを参照してください。
ワークフロー
-
ユーザーの目的を特定する:
- 新しい RAP BO を一から作成する
- 既存の BO に振る舞い(アクション、バリデーション、ディターミネーション)を追加する
- RAP BO を使用する EML ステートメントを記述する
- RAP 関連の問題をトラブルシューティングする
- RAP の概念を理解する
-
シナリオを特定する:
- マネージド(グリーンフィールド)かアンマネージド(ブラウンフィールド)か
- ドラフト対応かどうか
- 番号付けの方式:早期/後期、内部/外部/マネージド
- 単一エンティティかコンポジションツリー(ルート+子)か
-
RAP のレイヤーアーキテクチャに沿って 実装をガイドする:
- データモデリング(データベーステーブル → CDS ビューエンティティ)
- 振る舞い定義(BDL を使用した BDEF)
- 振る舞い実装(ABAP 振る舞いプール)
- ビジネスサービスの公開(サービス定義 → サービスバインディング)
-
正しい BDL および EML 構文を使用してコード例を提示する
RAP アーキテクチャのレイヤー
| レイヤー | 成果物 | 目的 |
|---|---|---|
| データモデリング | データベーステーブル、CDS ルート/子ビューエンティティ | データの永続化と意味的なデータモデル |
| 振る舞い定義 | BDEF(.bdef) | BDL を使用してトランザクションの振る舞い(操作、特性)を宣言する |
| 振る舞い実装 | ABAP 振る舞いプール(BP_*) | ハンドラークラスとセーバークラスにビジネスロジックを実装する |
| プロジェクション | CDS プロジェクションビュー、プロジェクション BDEF | 特定のサービスコンシューマー向けに BO を適合させる |
| ビジネスサービス | サービス定義、サービスバインディング | BO を OData サービスとして公開する |
実装タイプ
マネージド(グリーンフィールド)
- フレームワークがトランザクションバッファーと標準的な CRUD 操作を自動的に処理します
- 標準以外の操作(アクション、バリデーション、ディターミネーション)にのみカスタムコードが必要です
- 保存処理は自動的に行われます(
additional saveで拡張するか、unmanaged saveに置き換えられます)
managed implementation in class zbp_r_entity unique;
strict ( 2 );
アンマネージド(ブラウンフィールド)
- 開発者がトランザクションバッファーを用意し、すべての操作を実装します
- 既存のビジネスロジックを RAP に組み込む必要がある場合に使用します
unmanaged implementation in class zbp_r_entity unique;
strict ( 2 );
振る舞い定義(BDL)クイックリファレンス
BDEF の全体構造
managed implementation in class zbp_r_root unique;
strict ( 2 );
with draft;
define behavior for ZR_Root alias Root
persistent table zroot_tab
draft table zroot_d
etag master LocalLastChangedAt
lock master
total etag LastChangedAt
authorization master ( global )
late numbering
{
// Field characteristics
field ( readonly ) RootUUID, CreatedBy, CreatedAt, LastChangedBy, LastChangedAt;
field ( mandatory ) Description;
field ( numbering : managed ) RootUUID;
// Standard operations
create;
update;
delete;
// Association to child entity
association _Child { create; }
// Actions
action doSomething result [1] $self;
static action createFromTemplate parameter ZD_CreateParam result [1] $self;
internal action recalculate;
// Validations
validation validateDescription on save { create; field Description; }
// Determinations
determination setDefaults on modify { create; }
determination calcTotal on modify { field Quantity, Price; }
// Draft actions
draft action Resume;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft determine action Prepare
{
validation validateDescription;
}
// Side effects
side effects
{
field Quantity affects field TotalAmount;
field Price affects field TotalAmount;
determine action Prepare executed on field Description affects messages;
}
// Events
event created;
event deleted parameter ZD_DeletedEvent;
// Mapping
mapping for zroot_tab corresponding
{
RootUUID = root_uuid;
Description = description;
}
}
define behavior for ZR_Child alias Child
persistent table zchild_tab
draft table zchild_d
etag master LocalLastChangedAt
lock dependent by _Root
authorization dependent by _Root
{
field ( readonly ) ChildUUID, RootUUID;
field ( numbering : managed ) ChildUUID;
update;
delete;
association _Root;
mapping for zchild_tab corresponding
{
ChildUUID = child_uuid;
RootUUID = root_uuid;
}
}
プロジェクション BDEF
projection;
strict ( 2 );
use draft;
define behavior for ZC_Root alias Root
{
use create;
use update;
use delete;
use action doSomething;
use association _Child { create; }
}
define behavior for ZC_Child alias Child
{
use update;
use delete;
use association _Root;
}
BDL の主な要素
| 要素 | 構文 | 目的 |
|---|---|---|
| 管理番号付け | field ( numbering : managed ) KeyField; | フレームワークが UUID キーを自動的に割り当てます |
| 早期番号付け | early numbering | FOR NUMBERING ハンドラーを使用して、インタラクションフェーズでカスタムキーを割り当てます |
| 後期番号付け | late numbering | 保存シーケンスで adjust_numbers セーバーメソッドを使用してキーを割り当てます |
| ロックマスター | lock master | ルートエンティティが悲観的ロックを制御します |
| ロック依存 | lock dependent by _Assoc | 子エンティティが親にロックを委譲します |
| ETag | etag master FieldName | 楽観的同時実行制御 |
| 合計 ETag | total etag FieldName | ドラフト対応 BO に必須です |
| ドラフト | with draft; | BO 全体のドラフト処理を有効にします |
| 共同ドラフト | with collaborative draft; | 複数ユーザーによるドラフト編集 |
| 厳格モード | strict ( 2 ); | BDL の追加構文チェックを有効にします(最新バージョンを使用してください) |
ABAP Behavior Pool(ABP)
ハンドラークラス
CLASS lhc_root DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Standard operations (unmanaged only)
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE Root.
" Action implementation
METHODS doSomething FOR MODIFY
IMPORTING keys FOR ACTION Root~doSomething RESULT result.
" Validation
METHODS validateDescription FOR VALIDATE ON SAVE
IMPORTING keys FOR Root~validateDescription.
" Determination
METHODS setDefaults FOR DETERMINE ON MODIFY
IMPORTING keys FOR Root~setDefaults.
" Instance feature control
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR Root RESULT result.
" Instance authorization
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Root RESULT result.
ENDCLASS.
CLASS lhc_root IMPLEMENTATION.
METHOD doSomething.
" Read current instance data
READ ENTITIES OF zr_root IN LOCAL MODE
ENTITY Root
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(entities)
FAILED failed.
" Modify instances
MODIFY ENTITIES OF zr_root IN LOCAL MODE
ENTITY Root
UPDATE FIELDS ( Status )
WITH VALUE #( FOR entity IN entities
( %tky = entity-%tky
Status = 'DONE'
%control-Status = if_abap_behv=>mk-on ) )
FAILED failed
REPORTED reported.
" Fill result
result = VALUE #( FOR entity IN entities
( %tky = entity-%tky
%param = entity ) ).
ENDMETHOD.
METHOD validateDescription.
READ ENTITIES OF zr_root IN LOCAL MODE
ENTITY Root
FIELDS ( Description ) WITH CORRESPONDING #( keys )
RESULT DATA(entities).
LOOP AT entities INTO DATA(entity).
IF entity-Description IS INITIAL.
APPEND VALUE #( %tky = entity-%tky ) TO failed-root.
APPEND VALUE #( %tky = entity-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Description must not be empty' )
%element-Description = if_abap_behv=>mk-on
) TO reported-root.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD setDefaults.
READ ENTITIES OF zr_root IN LOCAL MODE
ENTITY Root
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(entities).
MODIFY ENTITIES OF zr_root IN LOCAL MODE
ENTITY Root
UPDATE FIELDS ( Status CreatedAt )
WITH VALUE #( FOR entity IN entities
( %tky = entity-%tky
Status = 'NEW'
%control-Status = if_abap_behv=>mk-on ) )
REPORTED reported.
ENDMETHOD.
ENDCLASS.
セーバークラス
CLASS lsc_root DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS finalize REDEFINITION.
METHODS check_before_save REDEFINITION.
METHODS save_modified REDEFINITION.
METHODS cleanup REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_root IMPLEMENTATION.
METHOD finalize.
" Final calculations before save
ENDMETHOD.
METHOD check_before_save.
" Final consistency checks
ENDMETHOD.
METHOD save_modified.
" Only needed for 'with additional save' or 'with unmanaged save'
" Raise business events here
IF create-root IS NOT INITIAL.
RAISE ENTITY EVENT zr_root~created
FROM VALUE #( FOR <cr> IN create-root
( %key = VALUE #( RootUUID = <cr>-RootUUID ) ) ).
ENDIF.
ENDMETHOD.
METHOD cleanup.
" Clear transactional buffer
ENDMETHOD.
METHOD cleanup_finalize.
" Rollback finalize changes on failure
ENDMETHOD.
ENDCLASS.
EML(Entity Manipulation Language)クイックリファレンス
EML は、RAP BO とプログラムでやり取りするための ABAP 言語です。主な操作は MODIFY ENTITY(作成/更新/削除/アクション実行)、READ ENTITIES、COMMIT ENTITIES、ROLLBACK ENTITIES です。
- 作成:
MODIFY ENTITY ... CREATE FIELDS ( ... ) WITH VALUE #( ( %cid = '...' ... ) ) - 読み取り:
READ ENTITIES OF ... ALL FIELDS WITH VALUE #( ( key = val ) ) RESULT DATA(result) - 更新:
MODIFY ENTITY ... UPDATE FIELDS ( ... ) WITH VALUE #( ( %tky = ... ) ) - 削除:
MODIFY ENTITY ... DELETE FROM VALUE #( ( %tky = ... ) ) - アクションの実行:
MODIFY ENTITY ... EXECUTE actionName FROM VALUE #( ( %tky = ... ) ) - ディープ作成:
%cid_refと%targetを使ってCREATE BY \_Assocを使用します
コード例を含む EML 構文の全容については、references/eml-quick-reference.md をご覧ください。
ドラフト処理
- BDEF ヘッダーで
with draft;を指定して有効にします - 各エンティティに個別の
draft tableが必要です - ドラフトテーブルには
"%admin": include sych_bdl_draft_admin_inc;を含める必要があります - ドラフトアクション(
Edit、Activate、Discard、Resume、Prepare)は暗黙的に提供されます - ドラフトインスタンスとアクティブインスタンスを区別するには、
%is_draftコンポーネント(またはそれを含む%tky)を使用します
RAP の保存シーケンス
| フェーズ | 呼び出されるメソッド | 目的 |
|---|---|---|
| 早期保存 | finalize → check_before_save →(失敗時:cleanup_finalize) | データの整合性を確保します |
| 後期保存 | adjust_numbers → save / save_modified → cleanup | データをデータベースに永続化します |
- 早期保存が失敗した場合(sy-subrc = 4)、インタラクションフェーズに戻ります
- 後期保存は後戻りできない段階です。コミットが成功するか、ランタイムエラーが発生します
BDEF の主要な派生型コンポーネント
| コンポーネント | 用途 |
|---|---|
%cid | コンテンツ ID — 新しいインスタンスの一意な仮識別子 |
%cid_ref | 同じ EML リクエスト内の %cid への参照 |
%key | 主キー項目 |
%tky | トランザクションキー(%key + %is_draft + %pid)— 推奨 |
%data | すべてのキー項目とデータ項目 |
%control | 提供/要求されている項目を示すフラグ |
%is_draft | ドラフトインジケーター(ドラフト有効化 BO のみ) |
%pid | 仮 ID(遅延採番のみ) |
%target | アソシエーションによる作成の対象インスタンス |
%param | アクション/関数のパラメーター値 |
ベストプラクティス
- 新しい BO では常に
strict ( 2 );を使用します - 将来にわたって使えるコードにするため、
%keyより%tkyを優先します(ドラフト/遅延採番の移行に対応します) - 後で参照しない場合でも、作成操作では常に
%cidを設定します - ハンドラーメソッドでは
IN LOCAL MODEを使用し、機能制御と権限チェックを回避します - データ整合性チェックにはバリデーションを、計算項目にはデターミネーションを実装します
- ハンドラーメソッドの役割を絞り、共通ロジックには ABP 補助クラスを使用します
- マネージド BO では、標準以外の操作に対してのみハンドラーメソッドを実装します
参考資料
- SAP ABAP チートシート — RAP BDL
- SAP ABAP チートシート — EML
- SAP Help — RAP 開発ガイド
- SAP Help — BDL リファレンス
- ABAP Flight リファレンスシナリオ
RAP のクリーンコアレベルに関する注意事項
| シナリオ | レベル | 注意事項 |
|---|---|---|
| コア範囲向けのカスタム RAP ベース Fiori アプリ | A | 新しいアプリケーションの目標状態 |
| リリース済み拡張ポイントを介した RAP ベース SAP Fiori アプリの拡張 | A | 推奨される拡張アプローチ |
| リリース済み CDS ビューとリリース済み API のみを使用する RAP BO | A | ハンドラー/セーバーのコードではリリース済み API のみに制限します |
クラシック API(transactional-consistent)を使用する RAP BO | B | RAP 内で安全に使用できるのは transactional-consistent のラベルが付いたクラシック API のみです |
| 内部オブジェクトまたは直接テーブル読み取りを使用する RAP BO | C | オブジェクトをラップし、ATC 免除を 1 つ作成します |
| カスタム SEGW/BOPF/UI5 アプリ | B | RAP を優先します。例外として、ノウハウや再利用の要件が考えられます |
| SEGW/BOPF/UI5 Fiori アプリの拡張 | B | 利用可能になった時点で、提供されている RAP アプリに移行します |
SE54 ベースの BC UI | B | RAP ベースのビジネス設定アプリを優先します |
重要なルール:クラシック API を RAP アプリケーション内で使用できるのは、Cloudification Repository で transactional-consistent のラベルが付いている場合のみです。それ以外のクラシック API は、RAP のトランザクションモデルを破損させる可能性があります。
関連するスキル
- cds-view-entities:RAP ビジネスオブジェクトの基盤となるデータモデリングに使用します
- abap-sql-amdp:RAP で複雑なデータベース操作を実装するために使用します
- authorization-iam:RAP の認可チェックを実装するために使用します
- odata:RAP ビジネスオブジェクトを OData サービスとして公開するために使用します
- rap-business-events:RAP でイベント駆動型パターンを実装するために使用します
- abap-cloud:クリーンコアレベルの分類とラッパーパターンに使用します
- badi-enhancement:標準の RAP BO を拡張するため、リリース済みの RAP BAdI を実装する際に使用します