SAP OData 编程指南
OData(Open Data Protocol)协议是一个开放的工业标准,用于定义 RESTFul API 的设计和使用。我的文章标题前加上 SAP 的前缀,只是为了表明这篇文章介绍的是 Jerry 在 SAP 项目开发中使用到 OData 的一些心得和经验。
目前 OData 被广泛用于 SAP Business Suite 和 SAP S/4HANA 的众多 Fiori 应用中,以及 SAP Customer Engagement Center 和一些正在开发的新一代云产品中。此外 OData 也是 SAP Cloud for Customer 推荐的一种将 C4C 和客户第三方应用集成的技术手段。关于这种集成方式,在我的另一篇文章里有所介绍:
本文会从 OData 服务的实现和消费这两个方面来介绍,目录如下:
在 SAP Business Suite 中进行 OData 开发
在 SAP S/4HANA 中进行 OData 开发
使用 ABAP 代码消费 OData 服务
使用 Java 代码 + Apache Olingo 消费 OData 服务
使用 UI5 消费 OData 服务
OData 性能测试
C4C 中的 OData 应用
XS OData Services
更多阅读
在 SAP Business Suite 中进行 OData 开发
以 SAP CRM 为例。SAP 对于很多 Fiori 应用都贴心地提供了可以云端试用的版本,通过如下链接访问:
https://www.sapfioritrial.com/
点击链接之后,在 Fiori Launchpad 里能看到 CRM 目录下存在若干 Tile,它们是 SAP 成都研究院 CRM Fiori 开发团队负责开发和维护的,Jerry 也曾经是这个团队的一员。随便点击一个 Tile, 比如 My Opportunities:
然后我们能看到该应用的明细页面了。在 Chrome 开发者工具的 Network 标签页,我们能观察到一个对于 metadata 的请求:
关于 Chrome 开发者工具的使用技巧,Jerry 曾经做过整理,单独写在另一篇文章里:
我们把这个 metadata 请求的 url 从 Chrome 开发者工具里拷贝出来,完整链接如下:
https://www.sapfioritrial.com/sap/opu/odata/sap/CRM_OPPORTUNITY/$metadata?sap-language=en&sap-client=001
直接在浏览器里访问这个链接,就能观察到包含在链接里名为 CRM_OPPORTUNITY 的 OData 服务的 metadata(元数据)。我们可以把一个 OData 服务的模型类比成一个 SAP Business Object,该模型同样由一个根节点和若干子节点组成,每个节点包含若干字段。某些节点提供了一些可以执行的逻辑,在 OData 协议里称这些逻辑为 function import(相当于 Business Object 里的 action)。不同节点之间通过定义 Navigation 建立关联关系——SAP 基于 Netweaver 的不同产品的建模方式思路都类似,可以触类旁通。
另一个重要的请求:
https://www.sapfioritrial.com/sap/opu/odata/sap/CRM_OPPORTUNITY/Opportunities?skip=0&top=20&$inlinecount=allpages&sap-client=001
在 Jerry 的另一篇文章 SAP UI 搜索分页技术 里已经对这个请求做过分析:
**skip=0&top=20:**通知后台执行分页搜索,只将满足查询条件的前 20 条记录从数据库取出,返回给 UI。
$inlinecount=allpages: 返回数据库满足搜索条件的记录数。因为 Jerry 未指定搜索条件,所以返回系统里 Opportunity 的总个数 1051。
下面简单介绍 SAP Business Suite 系统里如何开发 OData 模型和服务。
在动手开发前,我们需要先温习 Fiori 的架构。
在我的文章 SAP Fiori应用的三种部署方式里提到过这张图:
谈到 Fiori 开发时,就这张图而言,可以总结成两句话:
1. 在 ABAP Back-End 服务器上做 OData 模型和服务的开发
2. 在 ABAP Front-End 服务器上做 OData 服务的注册,以便让 Fiori 应用能够消费
首先我们到 ABAP Back-End 服务器上,使用事务码 SEGW 打开 CRM_OPPORTUNITY 这个 OData 服务。可以看到 Data Model 里包含了很多节点,每个节点实际上由一个 ABAP DDIC Structure 实现,节点上的每个字段对应着 Structure 上的字段。我们定义好 OData 模型包含哪些 Structure 之后,点击工具栏的 Generate Runtime Objects 按钮:
SAP Gateway 框架就会基于我们定义的 OData 模型,自动生成 4 个 ABAP 类和两个模型。
**MPC 和 MPC_EXT:**当消费者访问该服务的 metadata 时,这两个类负责把通过 ABAP DDIC Structure 描述的 metadata 信息转换成 OData 协议规范的格式并返回。每次开发人员修改 OData 模型,点击 Generate 按钮后,MPC 的代码都会重新生成。如果开发人员需要在模型上添加一些额外信息,比如一些版本控制信息或者相关注解(annotation),那么需要在 MPC_EXT 里通过 ABAP 代码实现。MPC_EXT 是 MPC 的子类,其代码不会被 Generate 按钮覆盖。一个例子如下:
**DPC 和 DPC_EXT:**包含了 OData 服务的实现,实际上也就是基于 OData 模型的 CRUD 操作,搜索操作和 function import 的实现。以 Opportunity 为例,因为该模型底层使用的是 CRM One Order 模型,所以 DPC_EXT 里包含了大量 CRM_ORDER_*等函数调用,CRM 顾问朋友们对这些函数应该非常熟悉。
在 ABAP Back-End 服务器做好 OData 开发后,登陆 ABAP Front-End 服务器,使用事务码**/IWFND/MAINT_SERVICE**将后台服务器做好的 OData 服务进行注册。
下图是 OData 服务在 ABAP Front-End 服务器的注册界面。从下图能看出理论上一台 ABAP Front-End 服务器可以连接多台 ABAP Back-End 服务器,
SAP 把这种 1:N 的关系称为 Multiple Origin Composition,典型的使用场景比如一家跨国企业,其美洲分公司的应用运行于 Back-End 服务器 1,欧洲分公司位于 Back-End 服务器 2。一个销售经理使用 Fiori 应用查看该企业某个时间段内全球的销售数据,则其 OData 实现会将这两台服务器的后台数据搜集起来,进行汇总并返回给 UI。具体细节请参考 SAP 帮助文档:
https://help.sap.com/doc/saphelp_hba/1.0/en-US/dd/f1ceb93a7d48fab4aa16efebc90e02/frameset.htm
关于 SEGW 更多开发细节,可以参考我的 SAP 同事环宇的公众号文章:
环宇有一个名为 Fiori 的公众号,介绍的全是 Fiori 知识。感兴趣的朋友可以关注一下。
在 S/4HANA 中进行 OData 开发
在我的公众号文章 Hello World, S/4HANA for Customer Management 1.0 里提到,CDS view 是 S/4HANA 里一个重要的建模方式。
我们还是来看个具体的例子。假设需要在 S/4HANA 里开发一个管理 Service Order 的 Fiori 应用,功能暂定为支持对 Service Order 的只读操作,即查询和浏览。借助 S/4HANA 的 CDS view 建模技术,我们不需要写一行 JavaScript,就可以自动生成一个满足需求的 Fiori 应用,听起来是不是很神奇?
我们需要创建一个 CDS view,用它来自动生成 OData 的模型和服务,即下图绿色的 Z_C_Service_Order_View。该 View 又从其他更底层的 CDS view 取数据,将 Service Order 的抬头,行项目,状态信息等数据聚合在一起。
CDS view 开发完毕后,只需要在事务码 SEGW 里将其通过 Reference->Data Source 加载进去:
就可以自动生成 OData 模型,以及前一章节提到的 MPC 和 DPC 各两套一共 4 个 ABAP Class,分别对应下图蓝色和红色区域所示,无需应用开发人员再写 ABAP 代码。
然后用 SAP WebIDE 创建一个新的 Fiori 应用,注意创建时不要使用普通的 SAPUI5 Application 模板,而采用 Smart Template Application 模板。在创建向导里指定之前基于 CDS view 自动生成的 OData 服务。
点击向导的 Finish 按钮,最终不用写一行 JavaScript 代码,就得到这样一个 Fiori 应用:
上图提到的 CDS view 的源代码,以及 Smart Template 的工作原理,都在我的博客里:
Create a CRM Service Order Fiori application within a couple of minutes
更进一步,如果想给这个自动生成的 Fiori 应用增添一些功能,例如支持对 Service Order 的修改和创建操作,请按照我的另外两篇博客去实现:
Enable CRM Service Order application with edit functionality
Enable CRM Service Order application with create functionality
值得一提的是,在 CDS view 里有一个强大的注解:
@OData.publish: true
和 SpringBoot 的注解能实现很多神奇的功能一样,被该注解定义过的 CDS view,能够不借助 SEGW 的帮助,自动生成 OData 模型和服务,进一步简化了开发人员做 OData 开发需要的配置,有助于开发人员快速构建出标准化的 OData 服务。
@OData.publish 这个注解的实现原理,请参考我的 CDS view 自学教程系列的第 4 部分:
Part 4 how does annotation @OData.publish work
OData 服务的消费
前面说了这么多都是 OData 模型和服务的开发,现在来谈谈如何消费。
使用 ABAP 代码消费 OData 服务
以消费 C4C Opportunity 的标准 OData 服务为例。
首先在 postman 里搞清楚如何使用 HTTP Post 加上 OData 的 $batch 操作来创建 Opportunity:
其实最主要的工作量就是把batch 请求的 body 通过下图代码里 insert_line 这个自定义宏操作的一系列字符串去填充。
因为 ABAP Netweaver 既可作为 Web Server,又可作为 Web Client,所以使用 ABAP 代码消费 OData 这种 RESTFul API,实质上是利用了 IF_HTTP_CLIENT 的 SEND 和 RECEIVE 方法,进行网络请求的发送和接收。
我在 SAP Community 上写过一个用 ABAP 代码消费 OData 服务的教程:
Consume standard C4C OData service via ABAP code
使用 Java 代码 + Apache Olingo 消费 OData 服务
相信大多数开发人员都不愿意像下面的代码这样直接操作 OData $batch body,既麻烦又容易出错。
于是在 Java 里就有了 Apache Olingo,一个开源库,您可以把它当成 OData 的 Java SDK,封装了 OData 底层的细节。$batch 操作需要填充的 BatchChangeSet 和 BatchChangeSetPart 在 Olingo 里都有了对应的类进行封装,看看下图使用 Java 代码调用 OData 服务进行 ServiceTicket 的创建,和上图 ABAP 代码进行比较,是不是从语义上看清晰了很多?
上图的完整 Java 代码,参考我的github
使用 UI5 消费 OData 服务
在 SAP UI5 官网上能找到详细的 API 说明。
Jerry 只补充两点原创内容。
1. UI5 OData API 的同步和异步参数。
2015 年 6 月时,我和德国一位负责 Quality 的同事就这个话题在半小时的电话会议里产生了争执。因为时间有限,我没能在电话里说服他,所以就有了这篇博客。德国同事看了之后,同意了我的意见。具体细节参考博客:
A Test on Fiori OData request Synchronous mode VS Asynchronous mode
下图是 5 个请求以同步模式发出在 Chrome 开发者工具 Network 标签页中观察到的时序:
下图是 5 个请求以异步模式发出:
2. 在 SAP 云平台的 CloudFoundry 环境下消费 ABAP On-Premise OData 服务
场景:在微信里消费 On-Premise 系统的 OData 服务。
详细步骤已经在我之前的微信公众号文章介绍过了。
OData 性能测试
1. 使用 Netweaver 提供的性能测试工具
详细介绍参考我的博客:
How to find OData performance trace and payload trace functionality
2. 使用 JMeter 测试 OData 服务在高并发场景下的性能指标
在 Jerry 工作过的客户项目里,很多客户提出了这种性能测试要求,比如同时发起 1000 个 Service Request 的 OData 创建请求,测量其平均响应时间。
Jerry 在这两篇博客里介绍了两种办法:
(1) 自己写 Java 代码,用多线程编程技术,每个线程发起一个 OData 创建请求,自己度量平均响应时间。
(2) 使用性能测试神器 JMeter,这样一行代码都不用写。
两种办法的具体介绍参考我的博客:
Kapsel OData plugin 原理讲解
SAP 移动解决方案的 Offline(离线)模式使用了 Kapsel OData plugin,用于将业务数据从后台系统抽取出来,保存于设备本地的离线存储区域。
关于其工作原理,参考 Jerry 做过的三个维度的分析:
How is OData request routed to Offline data store by Odata offline plugin
How is JavaScript code in OData offline plugin delegated to native Java code in Android
C4C 中的 OData 应用
Jerry 做过的 C4C 客户项目中对 OData 使用的一些分享:
Leverage C4C Odata notification to monitor C4C Opportunity change in CRM system
使用场景:在 C4C 创建业务数据后,利用这篇博客介绍的用法,能自动发送一个通知给其他系统/应用。可以作为一种轻量级的系统集成方案。
Expose TextCollection data belonging to a Custom BO via OData service
该解决方案我提供给了一个 Chinese C4C 客户。
Expose Custom BO logic implemented by ABSL via Custom OData service
通过 OData 将用 ABSL 实现的自定义逻辑暴露给第三方应用。
这个系列教程里,C4C 和微信的交互,60%使用了 C4C OData,40%使用了 C4C Web Service。
XS OData Services
HANA Studio 里开发的 HANA view 也能通过 HANA Extended Application Service 暴露成 OData 服务。
据我的成都同事介绍,SAP Customer Engagement Center 采用的就是这种方式。
更多介绍参考这篇 SAP 博客:
HANA Development: XS OData Services
更多阅读
所有更多阅读的链接都已经分布在文章的每一章节,这里为阅读方便起见,将部分链接再次统一罗列如下:
要获取更多 Jerry 的原创技术文章,请关注公众号"汪子熙"。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/d8666687817bb0f1e4a71571c】。文章转载请联系作者。
评论