笔者前一篇文章 SAP Fiori 注解 @ObjectModel.readOnly 工作原理解析,介绍了 SAP Fiori 编程模型里 @ObjectModel.readOnly
注解的工作原理。SAP Fiori 注解,是 ABAP Programming Model for SAP Fiori 的重要概念之一。
所谓注解(annotation),Java 和 JavaScript 开发人员一定不会陌生。
类似的,CDS 注解允许 ABAP 开发人员,将 ABAP 和特定于组件的元数据添加到任何CDS实体的源代码中。
根据一致性和注解有效性的评估实现细节,SAP CDS view 的注解分为以下两类:
- ABAP 注解:由 ABAP 运行时环境评估。
- Component 注解:由相关的 SAP 框架进行评估。
开发人员可以在元数据扩展中使用注解,为CDS视图定义特定于客户的元数据,而无需修改SAP 发布的标准 CDS 实体本身。使用元数据扩展时,可以覆盖数据定义中定义的特定注释值,或向实体添加额外的注释值。
注解可以添加在 CDS view 上或者 view field 上,下面是一个例子:
@AbapCatalog.sqlViewName: 'CUSTOMER'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
DEFINE VIEW cust_book_view_entity
AS SELECT FROM scustom
JOIN sbook
ON scustom.id = sbook.customid
{
@EndUserText.label: 'Customer ID'
scustom.id,
@EndUserText.label: 'Customer Name'
scustom.name,
@EndUserText.label: 'Customer Booking ID'
sbook.bookid
}
本文继续探讨另一个 注解 @OData.publish
的工作原理。
在SAP官网的ABAP Programming Model for SAP Fiori的帮助文档里,在OData Annotations目录下有对这个注解的介绍。
一旦加上了这个注解的CDS view激活时,会自动生成一个OData服务。
这个 OData 服务是如何自动生成的?这就是本文所要分享的内容。
SAP Fiori 编程模型支持一种新的 OData 服务的暴露方式,这种 OData 服务的模型定义,和运行时,基于 Service Adaptation Description Language 简称 SADL.
下面是一个例子:
@AbapCatalog.sqlViewName: 'SQL_VIEW_SAMPLE'
...
@OData.publish: true
define view CDS_VIEW_NAME as select from
...
}
使用 SAP ABAP Development Tool,打开 CDS 视图源代码编辑页面,将 OData 注解添加到 CDS 视图之后,就可以触发整个DDL 源的激活。ABAP开发工具将激活请求委托给 SADL 框架。SADL 生成若干个 SAP Gateway 构件(Artifacts),这些构件存储在应用服务器 AS ABAP 的后端,是SAP Gateway hub系统中激活和运行 OData 服务所必需的。
以上是通过 CDS view 暴露 OData 服务的理论知识。
假设我们对加了这个注解的CDS view激活后自动生成的OData服务的明细一无所知,从何处开始入手进行研究呢?
我创建了一个名为 zjerrytest20160311
的 view,然后加上这个注解,激活。根据我的经验,按照SAP惯例,自动生成的OData服务的名称应该也会包含0311这个字符串。
激活之后,我试着用0311作为关键字在OData服务的注册事务码/IWFND/MAINT_SERVICE里搜索,果然搜到了对应生成的OData服务:
在笔者之前的文章 ABAP 编程语言中 Class(类) 的设计原理剖析 曾经提到ABAP Netweaver的注册表 TADIR,按照0311进行查询,发现CDS view激活之后,除了OData服务本身,还自动生成了下列这些对象:
- IWMO: SAP Gateway Business Suite Enablement对应的模型
- IWSV: SAP Gateway Business Suite Enablement对应的服务
- CLAS: OData服务的实现类ZCL_ZJERRYTEST20160311
做个实验,当我把OData.publish的值设置为false,再次激活,发现类型为IWMO和IWSV的对象从注册表TADIR中消失了,这再次印证了二者是注解OData.publish设置为true之后激活CDS view生成的。
那么如何研究CDS view激活时,这两个对象的自动生成逻辑呢?
打开事物码 ST05,进入跟踪模式,激活CDS view,在数据库跟踪结果里果然发现了将自动生成的对象名称插入到注册表TADIR的OPEN SQL语句。
在ABAP里,在插入数据库表的OPEN SQL语句之前,必定有待插入数据的生成逻辑。
点击ST05里蓝色的眼镜图标,自动跳转到OPEN SQL语句里。设置断点,激活CDS view,断点触发:
从当前的调用栈往外追溯,发现在第21个调用栈帧,正是自动生成OData服务的地方:
CL_WB_DDLS_SECOBJ_HNDLR_SINGLE->IF_DDIC_WB_DDLS_SECOBJ_HANDLER~ON_ACTIVATION
这个方法首先根据delta_state判断出需要删除,新增或者更新的对象清单,分别存储在下图12到14行三个输出参数里。
举个例子,当我在一个已经激活过后的CDS view源代码里添加@OData.publish:true的注解,然后激活,此时该注解对于的EDIT_STATE为N(New), 而其他的注解因为没有任何变化,被标记为U(Unchanged).
此处会根据EDIT_STATE的值,进入对应的分支。
EDIT_STATE值为N的分支,则执行OData服务的创建,通过CL_SADL_GTK_ODATA_SERVICE_GEN完成,后缀GEN代表Generation.
从调试器里能看出,名称为ZJERRYTEST20160311的OData服务通过create_via_exposure方法被创建。
完整的调用栈:
本文其实也是另一个具体的例子,在不了解一段逻辑(无论框架层面或者应用层面)的情况下,如何使用ST05这个工具来找到设置断点的代码位置,从而找到问题分析的突破口。
总结
本文从一个开发人员的视角,深入介绍了 SAP Fiori 注解 @OData.publish 的工作原理。同时也展示了如何通过事物码 ST05,自行定位到 ABAP 框架自动生成 OData 服务资源的准确代码位置。