mcpField
R
rap

rap

github.com/likweitan开发7298 次安装2 周前更新
代码仓库

关于 rap

面向 ABAP Cloud 事务应用开发的 RAP 实用指南,涵盖设计选择、分层实现、行为定义和 EML,并说明 clean core 限制。

主要功能

  1. 01RAP 流程与场景选择
  2. 02业务对象分层设计
  3. 03BDL 行为定义
  4. 04ABP 处理器与保存类指南
  5. 05EML 操作示例
  6. 06草稿与保存序列说明

适用场景

  1. 01设计新的托管或非托管 RAP 业务对象
  2. 02为业务对象添加操作、校验或判定
  3. 03使用 EML 消费 RAP 业务对象
  4. 04排查 RAP 实现问题

安装

复制下面的命令,在终端中运行。

$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 RESTful Application Programming Model(RAP)在 ABAP Cloud 中构建事务型应用程序的指南。

Clean core 上下文:RAP 是 ABAP Cloud 开发的主要编程模型,其等级为 clean core Level A。面向 SAP Cloud ERP 核心范围的自定义 RAP Fiori 应用属于 Level A;通过已发布的扩展点扩展基于 RAP 的 SAP Fiori 应用,也属于 Level A。相比之下,基于 SEGW/BOPF/UI5 的应用及其扩展属于 Level B。请将 RAP 处理程序代码限制在已发布的 API 范围内,以保持在 Level A——只要调用一个内部对象,整个应用就会降级为 Level C。有关等级的详细信息,请参阅 abap-cloud 技能。

工作流

  1. 确定用户的目标:

    • 从头创建新的 RAP BO
    • 为现有 BO 添加行为(操作、验证、确定)
    • 编写 EML 语句以使用 RAP BO
    • 排查 RAP 相关问题
    • 了解 RAP 概念
  2. 识别场景:

    • 托管(绿地)还是非托管(棕地)
    • 是否启用草稿
    • 编号概念:早期/后期、内部/外部/托管
    • 单个实体还是组合树(根实体 + 子实体)
  3. 按照 RAP 分层架构指导实现:

    • 数据建模(数据库表 → CDS 视图实体)
    • 行为定义(使用 BDL 的 BDEF)
    • 行为实现(ABAP 行为池)
    • 业务服务公开(服务定义 → 服务绑定)
  4. 使用正确的 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通过 saver 方法 adjust_numbers 在保存序列中分配键
锁定主实体lock master根实体控制悲观锁定
锁定从属实体lock dependent by _Assoc子实体将锁定委托给父实体
ETagetag master FieldName乐观并发控制
总 ETagtotal etag FieldName启用草稿的 BO 必需
草稿with draft;为整个 BO 启用草稿处理
协作式草稿with collaborative draft;多用户草稿编辑
严格模式strict ( 2 );启用额外的 BDL 语法检查(使用最新版本)

ABAP 行为池(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.
Saver 类
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(实体操作语言)速查

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 = ... ) )
  • 深度创建:使用 CREATE BY \_Assoc,并搭配 %cid_ref 和 %target

有关包含代码示例的完整 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 );
  • 优先使用 %tky 而非 %key,以确保代码面向未来(可处理草稿/后期编号转换)
  • 即使之后不引用,也始终在创建操作中填写 %cid
  • 在处理程序方法中使用 IN LOCAL MODE,以绕过功能控制和授权检查
  • 实现用于数据一致性检查的验证,以及用于计算字段的确定逻辑
  • 让处理程序方法专注于特定任务;使用 ABP 辅助类共享逻辑
  • 对于托管 BO,仅为非标准操作实现处理程序方法

参考资料

RAP 的 Clean Core 级别说明

场景级别说明
面向核心范围的自定义 RAP Fiori 应用A新应用的目标状态
通过已发布扩展点扩展基于 RAP 的 SAP Fiori 应用A首选的扩展方式
仅使用已发布 CDS 视图和已发布 API 的 RAP BOA处理程序/保存程序代码仅限使用已发布的 API
使用经典 API(transactional-consistent)的 RAP BOB只有标记为 transactional-consistent 的经典 API 才能安全地用于 RAP
使用内部对象或直接读取表的 RAP BOC封装该对象并创建单个 ATC 豁免
自定义 SEGW/BOPF/UI5 应用B优先使用 RAP;例外情况可能涉及专业知识或复用
扩展 SEGW/BOPF/UI5 Fiori 应用B提供 RAP 应用后迁移至该应用
基于 SE54 的 BC UIB优先使用基于 RAP 的业务配置应用

关键规则:只有当经典 API 在 Cloudification Repository 中带有 transactional-consistent 标签时,才能在 RAP 应用中使用。其他经典 API 可能会破坏 RAP 的事务模型。

相关技能

  • cds-view-entities:用于建立 RAP 业务对象的基础数据模型
  • abap-sql-amdp:用于在 RAP 中实现复杂的数据库操作
  • authorization-iam:用于实现 RAP 授权检查
  • odata:用于将 RAP 业务对象公开为 OData 服务
  • rap-business-events:用于在 RAP 中实现事件驱动模式
  • abap-cloud:用于划分 Clean Core 级别并实现包装器模式
  • badi-enhancement:用于实现已发布的 RAP BAdI,以扩展标准 RAP BO

评论

支持 Markdown