关于 generate-rap-service
generate-rap-service 根据业务对象的自然语言描述,为 SAP RAP 生成表、CDS 视图、行为定义和 OData UI 服务等完整构件栈,面向 SAP 开发工作。它采用托管场景等默认设置,并可按系统能力和约束调整生成流程。
主要功能
- 01从描述生成 RAP 构件栈
- 02创建表、CDS 视图和行为定义
- 03生成元数据扩展与服务绑定
- 04检测 SAP 系统能力与约束
- 05应用 SAP 命名和类型惯例
适用场景
- 01从业务需求构建 RAP 服务
- 02为 Fiori Elements 准备 OData UI 服务
- 03按 SAP 系统版本适配生成流程
MCP 相关
技能通过 ARC-1 访问 SAP 系统,并可结合 mcp-sap-docs 查询文档。若官方 abap-mcp 服务已连接,符合条件时也可委托其生成构件。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ arc-mcp/ arc-1 --skill generate-rap-service安装后在 Claude Code 中输入/generate-rap-service确认已加载。
详细介绍
生成 RAP OData UI 服务
根据业务对象的自然语言描述,生成完整的 RAP OData UI 服务。创建完整的构件栈:数据库表、CDS 视图、行为定义、元数据扩展、服务定义和行为池类。
此技能通过结合 ARC-1(SAP 系统访问)和 mcp-sap-docs(文档与最佳实践),复现 SAP Joule 的“RAP 服务生成”能力。
v1 防护措施(快速路径):仅限托管场景、UUID 内部提前编号、默认单个根实体、优先实现标准 CRUD,可选草稿,优先使用 OData V4。对于多实体组合或大量自定义操作,优先使用 generate-rap-service-researched。
智能默认值(静默应用,不要询问)
| 设置 | 默认值 | 理由 |
|---|---|---|
| 包 | 用户的 Z* 包及传输请求 | 可用于生产环境;仅在用户明确要求时使用 $TMP |
| 键策略 | UUID(sysuuid_x16),托管编号 | 最简单,无冲突风险 |
| 行为场景 | 托管 | 框架处理 CRUD |
| OData 版本 | V4 | 当前 SAP 标准 |
| 草稿 | 对事务型 Fiori Elements UI 服务优先启用;根据版本和约束验证 | 是可编辑 FE 应用的最佳默认选择,但并非所有 RAP 服务都需要草稿 |
| 管理字段 | (本地部署)syuname/timestampl,或(BTP)abp_* 类型 | 适用于相应系统 |
| 严格模式 | strict ( 2 ),除非系统模式或 SAP 约束要求其他设置 | 当前 RAP 最佳实践,但并非通用要求 |
| 实体前缀 | Z + 实体名称(例如 ZTRAVEL) | SAP 标准 Z 命名空间 |
| 命名 | SAP 标准:ZI_、ZC_、ZSD_、ZSB_、ZBP_I_ | 与 SAP 文档保持一致 |
| 服务公开方式 | 默认使用 OData V4 UI 提供程序契约 | 最适合 Fiori Elements,除非用例以 API 为先 |
输入
用户提供业务对象的自然语言描述(例如,“一个包含代理机构、客户、目的地、开始/结束日期、总价、币种和状态字段的旅行预订应用”)。
只需提供业务对象描述。如果用户只提供描述,则应用智能默认值并立即继续。
用户也可以选择指定:
- 实体名称前缀(默认:根据描述自动生成)
- 包(必填——如果未提供则询问;仅当用户明确要求时才默认使用
$TMP) - 传输请求(仅非
$TMP包需要——参见步骤 1b) - 是否启用草稿(默认:BTP 上启用,本地部署上不启用)
- OData 版本(默认:V4)
步骤 1:检查系统功能
验证 SAP 系统是否支持 RAP/CDS,并检测系统类型。
SAPManage(action="probe")
如果需要更明确地确认语法和格式化程序行为的基准,也请读取:
SAPRead(type="SYSTEM")
SAPLint(action="list_rules")
SAPLint(action="get_formatter_settings")
**关键门槛:**如果探测明确报告 RAP/CDS 不可用,则停止并告知用户:在修复端点/系统设置之前,无法通过 ARC-1 创建 RAP 对象。
确定系统属于 BTP 还是本地部署——这会影响命名约定、语言版本和草稿处理。
步骤 1b:确定包和传输请求
如果用户未提供目标包,请询问。然后确定传输请求(仅当包为 $TMP 时跳过):
SAPTransport(action="check", objectType="DDLS", objectName="<first_object_name>", package="<package>")
此步骤会检查是否需要传输请求,并返回该包的现有传输请求。如果需要传输请求:
- 用户提供了传输请求:所有创建操作均使用该请求
- 找到现有传输请求:列出并请用户选择一个
- 没有可用的传输请求:创建一个:
SAPTransport(action="create", description="RAP Service: <Entity>", package="<package>")
如果需要传输请求但无法获取,请停止——对于非 $TMP 包,没有有效的传输请求,所有写入操作都会失败。
如果包尚不存在,且用户想要新建一个,请先创建:
SAPManage(action="create_package", name="<package>", description="<description>", transport="<transport_if_required>")
BTP 与 On-Prem 的差异
| 方面 | BTP(ABAP Cloud) | On-Prem(ABAP Platform) |
|---|---|---|
| 命名空间 | 仅限 Z*/Y* | Z*/Y* 或客户命名空间 |
| 语言版本 | ABAP for Cloud Development(严格模式) | Standard ABAP 或 ABAP for Cloud |
| 草稿表 | 必须显式创建(框架管理数据,而非表) | 必须显式创建 |
| OData 版本 | 优先使用 V4 | V2 或 V4 |
| 行为池 | ABSTRACT 类,仅限 ABAP Cloud | ABSTRACT 类,允许使用经典 ABAP |
| 表实体 | DEFINE TABLE ENTITY DDL 语法 | 经典 DDIC 表(SE11)或表实体 |
On-Prem 7.5x 快速检查要点
- 在 TABL 源代码中,使用
syuname+timestampl(而非abap.uname/abap.utclong)。 - 在 TABL 中,将
abap.char(1)用于类似布尔值的标志(而非abap.boolean)。 - 每个
abap.curr(...)字段上方都需要添加@Semantics.amount.currencyCode。 - 保持投影 BDEF 标头为
projection;(不要添加use etag标头行)。 - 保持启用 RAP 预检(默认设置),以便在激活操作反复尝试前拦截确定性的 TABL/BDEF/DDLX 问题。仅将
preflightBeforeWrite=false用作本地临时绕过方案。 - 如果行为池完整类写入因通用保存错误而失败,先使用
SAPWrite(action="scaffold_rap_handlers", ...)推导并应用签名,然后使用 quickfix 回退方案 +SAPWrite(action="edit_method")编写方法主体。
第 2 步:设计数据模型
根据用户的描述,设计完整的制品栈。遵循 SAP 命名约定:
命名约定
| 制品 | 模式 | 示例 |
|---|---|---|
| 数据库表(表实体) | Z<ENTITY>_D | ZTRAVEL_D |
| 接口 CDS 视图 | ZI_<Entity> | ZI_TRAVEL |
| 投影 CDS 视图 | ZC_<Entity> | ZC_TRAVEL |
| 元数据扩展 | ZC_<Entity> | ZC_TRAVEL |
| 接口行为定义 | ZI_<Entity> | ZI_TRAVEL |
| 投影行为定义 | ZC_<Entity> | ZC_TRAVEL |
| 访问控制(DCL) | ZI_<Entity>_DCL | ZI_TRAVEL_DCL |
| 服务定义 | ZSD_<Entity> | ZSD_TRAVEL |
| 服务绑定 | ZSB_<Entity>_V4 | ZSB_TRAVEL_V4 |
| 行为池类 | ZBP_I_<Entity> | ZBP_I_TRAVEL |
| 草稿表(如果启用草稿) | Z<ENTITY>_DD | ZTRAVEL_DD |
字段设计规则
每个实体都包含以下标准字段:
| 字段 | 类型 | 用途 |
|---|---|---|
key_uuid | sysuuid_x16 | UUID 主键(内部早期编号) |
created_by | syuname / abp_creation_user | 管理:创建者 |
created_at | timestampl / abp_creation_tstmpl | 管理:创建时间 |
last_changed_by | syuname / abp_locinst_lastchange_user | 管理:最后修改者 |
last_changed_at | timestampl / abp_locinst_lastchange_tstmpl | 管理:最后修改时间(本地实例) |
local_last_changed_at | timestampl / abp_lastchange_tstmpl | 管理:总 ETag 字段 |
根据用户描述添加业务字段。选择适当的 ABAP 类型:
- 文本:
abap.char(N)或abap.sstring(N) - 金额:
abap.curr(15,2),并配有货币代码字段(abap.cuky(5)) - 日期:
abap.dats - 状态:
abap.char(1),使用固定值 - 数量:
abap.quan(13,3),并配有单位字段(abap.unit(3)) - 整数:
abap.int4
面向用户的输出
将完整设计以表格形式呈现:
Proposed artifact stack for "Travel Booking":
| # | Type | Name | Description |
|---|------|------|-------------|
| 1 | TABL | ZTRAVEL_D | Database table entity |
| 2 | DDLS | ZI_TRAVEL | Interface CDS view entity |
| 3 | DCLS | ZI_TRAVEL_DCL | CDS access control (authorization rules) |
| 4 | BDEF | ZI_TRAVEL | Interface behavior definition |
| 5 | DDLS | ZC_TRAVEL | Projection CDS view entity |
| 6 | BDEF | ZC_TRAVEL | Projection behavior definition |
| 7 | DDLX | ZC_TRAVEL | Metadata extension (UI annotations) |
| 8 | SRVD | ZSD_TRAVEL | Service definition |
| 9 | CLAS | ZBP_I_TRAVEL | Behavior pool class |
| 10 | SRVB | ZSB_TRAVEL_V4 | Service binding |
Fields: key_uuid, agency_id, customer_id, destination, begin_date, end_date,
total_price, currency_code, status, created_by, created_at,
last_changed_by, last_changed_at, local_last_changed_at
询问用户:“是否要按此设计继续?(是 / 修改字段 / 更改名称)”
第 3 步:(可选)研究 RAP 模式
如果 mcp-sap-docs 可用,获取最新的 RAP 最佳实践。先使用参考类查询(includeSamples=false),然后仅在需要时使用示例(includeSamples=true):
search(query="RAP projection BO vs RAP BO interface", includeSamples=false, abapFlavor="<cloud|standard>")
search(query="RAP draft handling total etag draft-enabled associations", includeSamples=false, abapFlavor="<cloud|standard>")
search(query="service definition provider contracts odata_v4_ui odata_v4_webapi", includeSamples=false, abapFlavor="<cloud|standard>")
search(query="metadata-driven UI metadata extension RAP Fiori Elements", includeSamples=false, abapFlavor="<cloud|standard>")
使用返回的文档,确保注解模式、草稿处理、提供方契约和行为定义语法正确。
步骤 3b:(可选)委托给 SAP 官方 ABAP 生成器构建
如果 SAP 官方 ABAP MCP 服务与 ARC-1 一起连接(它随 VS Code 的 ABAP Development Tools 提供,并在 Eclipse ADT 3.60+ 中启用,在那里显示为 abap-mcp 服务),你可以将单根构建交给 SAP 自己的 Generate ABAP Repository Objects 框架,并跳过步骤 4–13 中的手动模板。这是 可选项——下面的每个步骤都有 ARC-1 备选方案,而且该生成器仅适用于有限的结构。
仅在以下条件全部满足时使用该生成器(否则跳到下方的 批量创建):
- 恰好 一个根实体——该生成器“最多生成一个实体”,不支持组合或层级结构。
- 托管模式 + 草稿模式——这是它唯一能生成的模式。
- 基表包含现代时间戳字段
last_changed : abp_lastchange_tstmpl和local_last_changed : abp_locinst_lastchange_tstmpl(生成器要求这些字段),或者使用 从头开始 的变体,由它为你生成表。 - 你接受这是 一次性操作——“并非为生成后修改而设计”。重新运行不会扩展现有 BO;后续更改需手动完成(这正是 ARC-1 的职责)。
3b-1. 探测服务
如果没有名为 abap_generators-list_generators 的工具(即官方 abap-mcp 服务),则表示它未连接 → 跳到 批量创建。不要询问用户——直接静默回退。
3b-2. 确定生成器 ID(ID 因版本而异——切勿硬编码)
调用 abap_generators-list_generators,选择 显示名称为 "OData UI Service"(用于 Fiori UI 应用)或 "OData Web API Service"(用于无界面 API)的生成器,然后使用它返回的 id。ID 因版本而异——以下为实时验证结果:
| 版本 | UI 服务 | Web API 服务 | 从头开始(也会生成表) |
|---|---|---|---|
| S/4HANA 2023 (SAP_BASIS 758) | uiservice | webapiservice | — |
| ABAP Platform 2025 (SAP_BASIS 816) | ui-service | webapi-service | x-ui-service |
如果未列出匹配的生成器,则此版本没有该框架 → 跳到 批量创建。
3b-3. 读取输入架构
abap_generators-get_schema 需要五个输入,且如果没有真实引用表就会报错:
abap_generators-get_schema(
generatorId = "<id from 3b-2>",
packageName = "<target package>", // your allowlisted package, or $TMP
referencedObjectType = "TABL",
referencedObjectName = "<existing base table>")
(从头开始的 x-ui-service 不需要引用表——请根据它返回的架构确认。)返回的架构中常见的配置项包括:软件包、数据模型(根实体名称 + EML 别名)、行为(草稿表名称)、服务投影名称、服务定义、服务绑定(OData 服务名称)、传输请求。读取实际架构并填写所有必填字段——不要假设本文档中的字段名称;它们因版本而异。
S/4HANA 2023(uiservice,引用表 ZARC1_DEMO_BOOK)上观察到的结构——已实时验证;你的情况可能不同,因此请读取实时响应:
dataModelEntity.cdsName → ZR_ARC1_DEMO_BOOK (root CDS)
implementationClass → ZBP_ARC1_DEMO_BOOK (behavior pool class)
draftTable → ZARC1_DEMO_BOOKD
serviceProjection.name → ZC_ARC1_DEMO_BOOK (projection CDS, exposed by the service)
serviceDefinition.name → ZUI_ARC1_DEMO_BOOK_O4
serviceBinding.name → ZUI_ARC1_DEMO_BOOK_O4 (binding type: OData V4 - UI)
3b-4. 生成
abap_generators-generate_objects(generatorId="<id>", <filled schema>)。这是一次 变更操作——请遵循与任何 ARC-1 写入相同的防护措施(使用允许列表中的软件包 + 真实传输请求,或 $TMP)。一次调用会创建 CDS 根实体 + 投影、BDEF + 行为类、元数据扩展(DDLX)、草稿表、服务定义和服务绑定。
3b-5. 验证,然后继续使用 ARC-1
使用 ARC-1(SAPActivate、SAPRead)或官方 abap_activate_objects 激活并验证。使用 ARC-1 发布服务绑定——SAPActivate(action="publish_srvb", name="<binding>")——因为在 7.5x 上,生成器会创建并激活 SRVB,但其自身的发布步骤会返回 406(发布作业内容协商失败),导致其保持 published:false 且没有运行时 URL。ARC-1 的 publish_srvb 会处理 758 内容类型,并将其设为 published:true(已在 S/4HANA 2023 上实时验证:生成的绑定从未发布变为已发布,随后 $metadata 返回 HTTP 200)。然后,对于单实体、一次性生成器无法完成的任何操作,使用 ARC-1——添加字段、组合/子项、操作及处理程序代码(SAPWrite action="edit_method")、判定、验证,以及所有后续编辑。
说明你采用了哪条路径(“通过 abap-mcp <id> 生成基础 BO,再通过 ARC-1 扩展”或“完全通过 ARC-1 构建”),以便让运行过程可审计。
批量创建(推荐)
与其在步骤 4-13 中逐个创建构件,不如使用批量创建,通过一次工具调用创建所有 RAP 构件:
SAPWrite(action="batch_create", objects=[
{type: "TABL", name: "<table_name>", description: "<Entity> Table", source: "<table_ddl>"},
{type: "DDLS", name: "ZI_<entity>", description: "<Entity> Interface View", source: "<interface_view_ddl>"},
{type: "DCLS", name: "ZI_<entity>_DCL", description: "<Entity> Access Control", source: "<interface_dcl_source>"},
{type: "DDLS", name: "ZC_<entity>", description: "<Entity> Projection View", source: "<projection_view_ddl>"},
{type: "BDEF", name: "ZI_<entity>", description: "<Entity> Interface Behavior", source: "<interface_bdef>"},
{type: "BDEF", name: "ZC_<entity>", description: "<Entity> Projection Behavior", source: "<projection_bdef>"},
{type: "DDLX", name: "ZC_<entity>", description: "<Entity> Metadata Extension", source: "<ddlx_source>"},
{type: "SRVD", name: "ZSD_<entity>", description: "<Entity> Service Definition", source: "<srvd_source>"},
{type: "CLAS", name: "ZBP_I_<entity>", description: "<Entity> Behavior Pool", source: "<class_source>"},
{type: "SRVB", name: "ZSB_<entity>_V4", description: "<Entity> Service Binding", serviceDefinition: "ZSD_<entity>", bindingType: "ODataV4-UI"}
], package="<package>", transport="<transport>")
对象按数组顺序创建并激活——请将依赖项放在前面(表在 CDS 视图之前、DCLS 在 DDLS 之后、CDS 视图在 BDEF 之前、行为池在接口 BDEF 之前)。批次会在首次失败时停止,并报告哪些对象成功、哪些失败。
如果所有构件共用相同的程序包和传输请求,请在顶层设置 package 和 transport。如果某个批次项需要覆盖其中任一值,请在该对象上设置 package 和/或 transport;对象级值优先。
对于存在跨同级引用的对象组,请传入 activateAtEnd: true(例如,组合关联的 DDLS 中,父项的 composition [0..*] of ZR_CHILD 引用了同一批次中的子项)。ARC-1 会为每个对象写入非活动草稿,然后发出一次最终的 activateBatch——SAP 激活器会看到整个对象图,并在一次处理中解析跨对象引用。不使用此标志时,父项的内联激活会失败,并显示 "data source ZR_CHILD does not exist or is not active"。
如果批量创建失败,请退回到以下顺序创建方式(步骤 4-13)。
步骤 4:创建数据库表(顺序创建回退方案)
通过 CDS DDL 创建表实体。
SAPWrite(action="create", type="TABL", name="<table_name>", package="<package>", transport="<transport>", source="<ddl_source>")
表实体 DDL 模板
@EndUserText.label : '<Entity description>'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table <table_name> {
key client : abap.clnt not null;
key key_uuid : sysuuid_x16 not null;
<business_field_1> : <type>;
<business_field_2> : <type>;
// ... more business fields
created_by : syuname;
created_at : timestampl;
last_changed_by : syuname;
last_changed_at : timestampl;
local_last_changed_at : timestampl;
}
激活表:
SAPActivate(type="TABL", name="<table_name>")
回退方案:如果表实体创建失败(例如,在较旧的本地部署系统上),请指导用户通过 SE11 或 ADT 手动创建表,并提供字段列表和类型。
步骤 5:创建接口 CDS 视图
SAPWrite(action="create", type="DDLS", name="ZI_<entity>", package="<package>", transport="<transport>", source="<ddl_source>")
接口视图 DDL 模板
@AccessControl.authorizationCheck: #MANDATORY
@EndUserText.label: '<Entity description>'
define root view entity ZI_<Entity>
as select from <table_name>
{
key key_uuid as KeyUuid,
<business_field_1> as <CamelCaseAlias1>,
<business_field_2> as <CamelCaseAlias2>,
// ... more business fields
@Semantics.amount.currencyCode: 'CurrencyCode'
total_price as TotalPrice,
currency_code as CurrencyCode,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt
}
激活:
SAPActivate(type="DDLS", name="ZI_<entity>")
步骤 5a:创建接口访问控制(DCLS)
为接口视图创建基本 CDS 访问控制角色。
SAPWrite(action="create", type="DCLS", name="ZI_<entity>_DCL", package="<package>", transport="<transport>", source="<dcl_source>")
接口 DCL 模板
@EndUserText.label: '<Entity description> Access Control'
@MappingRole: true
define role ZI_<Entity>_DCL {
grant select on ZI_<Entity>
where inheriting conditions from super;
}
激活:
SAPActivate(type="DCLS", name="ZI_<entity>_DCL")
步骤 5b:创建草稿表(启用草稿时)
如果启用了草稿,请先创建草稿表实体,再创建引用它的行为定义。RAP 框架会管理草稿数据在该表中的运行时持久化,但必须显式创建该表本身。
SAPWrite(action="create", type="TABL", name="<draft_table>", package="<package>", transport="<transport>", source="<ddl_source>")
草稿表实体 DDL 模板
@EndUserText.label : '<Entity description> - Draft'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table <draft_table> {
key client : abap.clnt not null;
key key_uuid : sysuuid_x16 not null;
<business_field_1> : <type>;
<business_field_2> : <type>;
// ... same business fields as the main table
created_by : syuname;
created_at : timestampl;
last_changed_by : syuname;
last_changed_at : timestampl;
local_last_changed_at : timestampl;
}
激活草稿表:
SAPActivate(type="TABL", name="<draft_table>")
注意:在 BTP ABAP Environment 上,仍必须显式创建草稿表——框架会在运行时管理草稿数据的持久化,而非表的存在。
步骤 6:创建接口行为定义
SAPWrite(action="create", type="BDEF", name="ZI_<entity>", package="<package>", transport="<transport>", source="<bdef_source>")
使用草稿
managed implementation in class ZBP_I_<Entity> unique;
strict ( 2 );
with draft;
define behavior for ZI_<Entity> alias <Entity>
persistent table <table_name>
draft table <draft_table>
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master ( instance )
{
field ( readonly )
KeyUuid,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedAt;
field ( numbering : managed )
KeyUuid;
create;
update;
delete;
draft action Resume;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft determine action Prepare;
}
不使用草稿
managed implementation in class ZBP_I_<Entity> unique;
strict ( 2 );
define behavior for ZI_<Entity> alias <Entity>
persistent table <table_name>
etag master LocalLastChangedAt
lock master
authorization master ( instance )
{
field ( readonly )
KeyUuid,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedAt;
field ( numbering : managed )
KeyUuid;
create;
update;
delete;
}
请勿单独激活接口 BDEF——它引用尚不存在的行为池类(ZBP_I_)。创建类后,将在批量激活步骤中激活该定义。
步骤 7:创建投影 CDS 视图
SAPWrite(action="create", type="DDLS", name="ZC_<entity>", package="<package>", transport="<transport>", source="<ddl_source>")
投影视图 DDL 模板
@AccessControl.authorizationCheck: #MANDATORY
@EndUserText.label: '<Entity description> - Projection'
@Metadata.allowExtensions: true
@Search.searchable: true
define root view entity ZC_<Entity>
provider contract transactional_query
as projection on ZI_<Entity>
{
key KeyUuid,
@Search.defaultSearchElement: true
<BusinessField1>,
@Search.defaultSearchElement: true
<BusinessField2>,
// ... more business fields
TotalPrice,
CurrencyCode,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedAt
}
使用 @Search.defaultSearchElement: true 标记最重要的业务字段(通常是名称、ID 和描述)。
激活:
SAPActivate(type="DDLS", name="ZC_<entity>")
步骤 8:创建投影行为定义
SAPWrite(action="create", type="BDEF", name="ZC_<entity>", package="<package>", transport="<transport>", source="<bdef_source>")
带草稿
projection;
strict ( 2 );
use draft;
define behavior for ZC_<Entity> alias <Entity>
{
use create;
use update;
use delete;
use action Resume;
use action Edit;
use action Activate;
use action Discard;
use action Prepare;
}
不带草稿
projection;
strict ( 2 );
define behavior for ZC_<Entity> alias <Entity>
{
use create;
use update;
use delete;
}
不要单独激活投影 BDEF——它使用 use create、use update、use delete,这些语句引用接口 BDEF(ZI_),而该 BDEF 尚未激活。所有构件创建完成后,它将在批量激活步骤中激活。
步骤 9:创建元数据扩展(DDLX)
SAPWrite(action="create", type="DDLX", name="ZC_<entity>", package="<package>", transport="<transport>", source="<ddlx_source>")
元数据扩展模板
@Metadata.layer: #CUSTOMER
@UI: {
headerInfo: {
typeName: '<Entity Name>',
typeNamePlural: '<Entity Name Plural>',
title: { type: #STANDARD, value: '<MainBusinessField>' },
description: { type: #STANDARD, value: '<SecondaryField>' }
}
}
annotate view ZC_<Entity> with
{
@UI.facet: [
{
id: 'idIdentification',
type: #IDENTIFICATION_REFERENCE,
label: 'General Information',
position: 10
}
]
@UI.hidden: true
KeyUuid;
@UI: {
lineItem: [{ position: 10, importance: #HIGH }],
identification: [{ position: 10 }],
selectionField: [{ position: 10 }]
}
<BusinessField1>;
@UI: {
lineItem: [{ position: 20, importance: #HIGH }],
identification: [{ position: 20 }],
selectionField: [{ position: 20 }]
}
<BusinessField2>;
// ... more business fields with incrementing positions
@UI: {
lineItem: [{ position: 50, importance: #MEDIUM }],
identification: [{ position: 50 }]
}
TotalPrice;
@UI.hidden: true
CreatedBy;
@UI.hidden: true
CreatedAt;
@UI.hidden: true
LastChangedBy;
@UI.hidden: true
LastChangedAt;
@UI.hidden: true
LocalLastChangedAt;
}
位置编号:每次递增 10。为最相关的业务字段(在窄屏上显示)分配 importance: #HIGH,为次要字段分配 #MEDIUM。为用户可能要筛选的字段添加 @UI.selectionField。
激活:
SAPActivate(type="DDLX", name="ZC_<entity>")
步骤 10:创建服务定义
SAPWrite(action="create", type="SRVD", name="ZSD_<entity>", package="<package>", transport="<transport>", source="<srvd_source>")
服务定义模板
@EndUserText.label: '<Entity description> Service'
define service ZSD_<Entity>
provider contracts odata_v4_ui
{
expose ZC_<Entity> as <Entity>;
}
如果主要使用场景是 API/集成,而不是 Fiori Elements,请同时切换提供方契约和绑定类型:
define service ZSD_<Entity>
provider contracts odata_v4_webapi
{
expose ZC_<Entity> as <Entity>;
}
激活:
SAPActivate(type="SRVD", name="ZSD_<entity>")
步骤 11:创建行为池类
请在批量激活之前创建行为池类——接口 BDEF 通过 implementation in class ZBP_I_<Entity> 引用此类。
编写代码前,可选择运行 SAP PrettyPrinter,使类源代码符合系统的关键字样式和缩进规范:
SAPLint(action="format", source="<class_source>", name="ZBP_I_<entity>")
SAPWrite(action="create", type="CLAS", name="ZBP_I_<entity>", package="<package>", transport="<transport>", source="<class_source>")
行为池类模板
CLASS zbp_i_<entity> DEFINITION
PUBLIC ABSTRACT FINAL
FOR BEHAVIOR OF zi_<entity>.
ENDCLASS.
CLASS zbp_i_<entity> IMPLEMENTATION.
ENDCLASS.
激活:
SAPActivate(type="CLAS", name="ZBP_I_<entity>")
步骤 12:批量激活所有构件
首先,可选择检查是否有可能造成干扰的未激活对象:
SAPRead(type="INACTIVE_OBJECTS")
**注意:**在某些系统中,如果 /sap/bc/adt/activation/inactive 端点不可用,此检查可能会返回 404。如果是这样,请跳过此检查并继续。
一起激活所有构件,以解决跨对象依赖关系:
SAPActivate(objects=[
{type:"TABL", name:"<table_name>"},
{type:"DDLS", name:"ZI_<entity>"},
{type:"DCLS", name:"ZI_<entity>_DCL"},
{type:"CLAS", name:"ZBP_I_<entity>"},
{type:"BDEF", name:"ZI_<entity>"},
{type:"DDLS", name:"ZC_<entity>"},
{type:"BDEF", name:"ZC_<entity>"},
{type:"DDLX", name:"ZC_<entity>"},
{type:"SRVD", name:"ZSD_<entity>"}
])
**注意:**激活会返回结构化响应,其中包含详细的错误/警告消息,包括行号和 URI。错误会阻止激活;警告不会阻止激活,但应予以检查。
如果批量激活失败,请按依赖顺序逐个激活:
- 表实体
- 接口 CDS 视图
- 接口访问控制(DCLS)
- 行为池类
- 接口行为定义
- 投影 CDS 视图
- 投影行为定义
- 元数据扩展
- 服务定义
如果由于缺少 METHODS ... FOR ... 签名导致行为池激活失败:
- 使用
SAPWrite(action="scaffold_rap_handlers", type="CLAS", name="<bp_class>", bdefName="ZI_<entity>")列出缺失的签名。 - 如有需要,使用
autoApply=true重新运行,以便将签名注入类声明并生成空方法桩。 - 如果仍无法解析签名,并且有可用的建议,请使用
SAPDiagnose(action="quickfix", ...)和SAPDiagnose(action="apply_quickfix", ...)。 - 如果以上方法均无效,请使用 ADT 编辑器生成快速修复,然后使用
SAPWrite(action="edit_method", ...)修改方法体。
对于任何激活失败的对象,请运行语法检查以定位问题:
SAPRead(type="SYNTAX", objectType="<type>", name="<name>")
步骤 13:创建并发布服务绑定
创建服务绑定:
SAPWrite(action="create", type="SRVB", name="ZSB_<entity>_V4", package="<package>", transport="<transport>",
serviceDefinition="ZSD_<entity>", bindingType="ODataV4-UI", description="<Entity> OData V4 Service")
激活服务绑定:
SAPActivate(type="SRVB", name="ZSB_<entity>_V4")
发布服务绑定(使 OData 服务可用):
SAPActivate(action="publish_srvb", name="ZSB_<entity>_V4")
检查发布状态和服务 URL:
SAPRead(type="SRVB", name="ZSB_<entity>_V4")
⚠️ 检查点:确认 SRVB 读取结果显示 published: true、预期的绑定类型和服务 URL。对于 OData V4 绑定,发布/取消发布操作作用于整个绑定。
步骤 14:验证完整服务
读取关键构件并运行最终检查:
SAPRead(type="DDLS", name="ZI_<entity>")
SAPRead(type="DCLS", name="ZI_<entity>_DCL")
SAPRead(type="BDEF", name="ZI_<entity>")
SAPRead(type="DDLS", name="ZC_<entity>")
SAPRead(type="SYNTAX", objectType="CLAS", name="ZBP_I_<entity>")
提供摘要检查清单:
RAP Service Generation Complete!
Created artifacts:
[x] Database table entity: <table_name>
[x] Interface CDS view: ZI_<Entity>
[x] Interface access control: ZI_<Entity>_DCL
[x] Interface behavior definition: ZI_<Entity>
[x] Projection CDS view: ZC_<Entity>
[x] Projection behavior definition: ZC_<Entity>
[x] Metadata extension: ZC_<Entity>
[x] Service definition: ZSD_<Entity>
[x] Behavior pool class: ZBP_I_<Entity>
[x] Service binding: ZSB_<Entity>_V4
[x] Service binding published
Next steps:
- Add validations and determinations (use generate-rap-logic skill)
- Add value helps for business fields
- Add custom actions if needed
- Generate unit tests (use generate-abap-unit-test skill)
- Register in FLP launchpad (use SAPManage flp_create_catalog, flp_create_tile, flp_create_group)
- Create proper DOMA/DTEL for reusable typing (use SAPWrite with type=DOMA/DTEL)
- Attach SKTD documentation to the service or BDEF (optional)
- Review later iterations with `SAPTransport(action="history", type=…, name=…)` for current lock/assignment status plus `SAPRead(type="VERSIONS", ...)` for actual revision history
错误处理
常见问题与修复方法
| 错误 | 原因 | 修复方法 |
|---|---|---|
| DDLS/BDEF 上出现 415 Unsupported Media Type | RAP/CDS 端点未按预期响应 | 使用 SAPManage(action="probe") 检查系统信息。确认 ICF 服务已激活。尝试在 ADT 中创建对象,以确认系统功能是否可用。 |
创建时出现 Resource X does already exist | 对象已存在或与存根冲突 | 改用 SAPWrite(action="update", ...) 并重新发送完整源代码。不要盲目重试创建。 |
| 激活错误:未找到依赖项 | 对象激活顺序错误 | 按依赖顺序依次激活(回退方案见步骤 12) |
| 未找到草稿表 | 尚未创建草稿表 | 先创建草稿表实体,或从 BDEF 中移除 with draft |
| 字段映射不完整 | BDEF 字段名与 CDS 别名不匹配 | 确认 CDS 字段别名与 BDEF 字段引用完全一致 |
| 未找到 ETag 字段 | 缺少 LocalLastChangedAt 或名称拼写错误 | 确认 CDS 视图中存在管理字段,且别名正确 |
| 未找到行为池 | 类名与 BDEF 的 implementation in class 不匹配 | 确保 BDEF 中的类名与创建的类完全一致 |
创建/保存 BDEF 时出现通用错误 [?/011] | 对于 RAP 处理程序声明,行为池完整类的保存路径不稳定 | 保持类定义精简,使用快速修复生成签名(MCP 或 ADT),然后使用 edit_method 编写方法体 |
| Lint 阻止写入 | 生成的代码存在 lint 警告 | 检查 lint 发现的问题,调整代码模式以通过 lint 规则 |
| 不支持创建表实体 | 本地旧版系统 | 手动通过 SE11 创建表,并提供字段列表 |
| 需要传输请求 | 非 $TMP 包未关联传输请求 | 使用 SAPTransport(action="check") 查找或创建传输请求——参见步骤 1b |
| 创建时发生锁冲突 | 对象被其他用户/传输请求锁定 | 等待或使用其他名称;使用 SAPTransport(action="list") 检查是否存在冲突的传输请求 |
| 缺少货币引用注解 | abap.curr 字段没有货币语义注解 | 在每个金额字段上方添加 @Semantics.amount.currencyCode,并确保存在 abap.cuky 字段 |
预期为 "draft or side",而不是 "etag" | 7.5x 上的投影 BDEF 头部语法无效 | 头部仅保留 projection; |
说明
BTP 与本地部署系统概要
- BTP:仅允许 Z*/Y* 命名空间,强制使用 ABAP Cloud 语法,必须显式创建草稿表(框架在运行时管理草稿数据),优先使用 V4 OData,BDEF 中使用
strict ( 2 ),采用表实体 DDL 语法,仅使用已发布的 SAP API。 - 本地部署系统:命名空间限制较少,行为池中允许使用经典 ABAP(不推荐),可能需要显式创建草稿表,可使用 V2 或 V4,
strict级别取决于版本。
此技能不会执行的操作(v1)
- 复杂组合/子层级结构:对于多实体 BO 和分两阶段推出,请使用
generate-rap-service-researched。 - 自定义操作:除了草稿操作外,不声明
action。之后请使用 generate-rap-logic 技能。 - 确定和验证:不包含业务逻辑。之后请使用 generate-rap-logic 技能添加这些内容。
- 值帮助:不添加
@Consumption.valueHelpDefinition注解。请手动添加。 - 特性控制/副作用:除标准 CRUD 外,不添加由后端驱动的 UI 行为。当 UI 需要动态启用或重新计算提示时,请手动添加。
- 非托管/抽象 BO:仅支持带 UUID 键的托管场景。
- DOMA/DTEL 创建:使用内联类型。对于生产服务,请随后使用
SAPWrite(type="DOMA"/"DTEL")创建合适的域和数据元素。 - FLP 注册:不会自动注册到 Fiori Launchpad。之后请使用
SAPManageFLP 操作。
何时使用此技能
- 从头开始创建新的 RAP 应用时
- 用户用自然语言描述业务对象时
- 快速搭建 Fiori Elements 应用原型时
- 不适用于扩展现有 RAP 服务(请使用手动编辑或 generate-rap-logic)
- 不适用于包含多个实体的复杂数据模型(v1 仅支持单个根实体)