使用 SAP Cloud Application Programming 编程模型开发一个图书管理 OData 服务
最近不断有 SAP 从业者在社交媒体上向我我咨询,询问关于 SAP Cloud Application Programming(简称 CAP) 的相关开发流程。
早在 SAP 2019 TechEd 上,SAP CTO Juergen Mueller 向 SAP 生态圈传递了一条重要信息:身处云时代大环境下的 SAP 从业者,如何选择最适合自己的 SAP 开发方式?
Juergen Mueller 给出了下图所示的决策树,帮助大家进行技术选型:
决策树中展示的主要分支解释如下:
如果待实现的需求,能够通过非代码方式来完成,可以尝试工作流(Workflow) 或者低代码解决方案(Low-Code),比如 SAP RAD by Mendix,细节可以参考 Jerry 这篇文章:SAP 云平台上的 Low Code Development(低代码开发)解决方案。
如果只能通过编码实现需求,则可以选择基于 ABAP 技术栈的 RAP(Restful ABAP Programming) 编程模型,或者非 ABAP 技术栈的 Cloud Application Programming 模型。
SAP Cloud Application Programming 模型的准确定义是什么?
SAP 官网的定义是:SAP Cloud Application Programming 是一套由开发语言,开发工具和库有机集成的框架,提供了一种高效,快捷,全栈式的企业级服务和应用开发手段。CAP 包含一套开发最佳实践,让开发者能够专注于应用内具体业务逻辑的开发,而无需分心将精力花在重复的底层基础设施功能的实现上去。
Jerry 在 2019 年 SAP TechEd 结束后,曾经写过一篇文章,通过一个在线书店的例子,介绍了 SAP Cloud Application Programming 编程模型的使用方式:
使用Cloud Application Programming模型开发OData的一个实际例子
如果大家照着文章里介绍的步骤,自己动手实践一遍,不难发现,我们绝大部分工作量都花在了思考并设计在线书店里涉及到的业务领域模型(Domain Model),比如书籍,书籍类别,作者,订单及模型间的相互关联关系。而这些模型本身的增删改查和持久化逻辑等更底层的技术实现,全部由 SAP CAP 本身完成,无需应用开发人员操心。SAP CAP 期望通过这种设计,来提高企业级应用的开发效率和健壮性。
距离 Jerry 前一篇文章已经过去两年了,最近我抽时间查询了 SAP 官网关于 SAP CAP 开发流程的介绍,发现其在 2019 年的基础上,从 CAP 提供的开发工具的使用角度上说,没有太大的变化,但不少细节之处进行了优化,使用起来感觉更加顺畅。
本文介绍的使用 SAP Cloud Application Programming 模型开发在线书店的过程,分为下列四个步骤:
创建业务模型
将业务数据导入数据库表
开发 OData 服务,将业务数据暴露给消费者
开发前端 UI 页面,通过 OData 服务,将步骤 2 准备的业务数据展示出来
本文使用到的源代码,在 SAP 官网上能够下载。
本文使用基于 nodejs 的 SAP Cloud Application Programming 完成在线书店应用的开发,因此需要安装并配置 nodejs 开发环境。
创建业务模型
首先使用命令行,安装 CAP 的 SDK 工具:
npm i -g @sap/cds-dk
完成之后敲 cds 命令,确保能看到下列输出:
然后创建一个空的 CAP 项目:
cds init bookshop
cds init 命令行创建出来的项目,本质上还是一个 nodejs 应用,包含了 CAP 应用的骨架。我们接下来需要进入上图标注了三个序号的文件夹里,进行相应的业务逻辑开发。
app 文件夹里存放的是 CAP 应用的前端 UI 页面,这些页面消费该 CAP 应用提供的 OData 服务,将业务数据以 UI 方式展示出来。可以基于任何前端框架实现。
db 文件夹里存放的是 CAP 的业务模型定义,以及持久化数据库相关的资源。
srv 文件夹里存放的是 OData 服务定义。这些 OData 服务负责将 db 里定义的业务模型承载的业务数据暴露给消费者,比如被 app 文件夹里开发的前端应用所消费。
用 Visual Studio Code 打开新建好的 CAP 项目,首先在 db 文件夹的 schema.cds 文件里,创建在线书店业务模型。使用关键字 entity 定义一个名为 Books 的模型。
冒号后面的 managed,包含了几乎所有业务模型都需要定义的 Administrative 信息,即创建时间,创建者,修改时间,修改者。因此 SAP CAP 出于重用目的,将这四个字段包裹在名为 managed 的 aspect 中。应用人员定义的业务模型,通过 : managed 的语法将其包含入内。
ABAP 开发人员可以将这种机制,类比成 ABAP DDIC 的 Include Structure.
采用同样的语法,定义书籍作者(Authors) 和书籍类别(Genres)模型后,我们下一个需要考虑的问题就是,如何插入业务数据到这些模型对应的数据库表里。
将业务数据导入数据库表
SAP CAP 提供了一种比较简单的数据导入方式,即本地维护一些包含业务数据的 csv 文件,将这些 csv 文件导入到模型对应的数据库表里。无独有偶,SAP Commerce Cloud (电商云)也支持这种 csv 文件导入的方式,实现数据导入功能。这种数据导入方式,在 SAP Commerce Cloud 里称为 ImpEx (Import & Export 的简写).
我在 db 文件夹下 schema.cds 里定义的命名空间为 sap.capire.bookshop, 因此为了使用 csv 文件向这个命名空间里的数据库表导入数据,需要按照下列命名规范创建 csv 文件:
<命名空间>-<模型名称>.csv
比如我导入数据库的作者数据,创建的 csv 文件名为:sap.capire.bookshop-Authors.csv
书籍数据:sap.capire.bookshop-Books.csv
书籍类别数据:sap.capire.bookshop-Genres.csv
csv 文件维护完毕之后,执行 cds deploy 命令,将 csv 文件导入到数据库里。命令中 sqlite 冒号后面是我指定的数据库名称:my.db
cds deploy --to sqlite:my.db
数据导入成功后,在 Visual Studio Code SQLite Explorer 里能浏览数据库表及其内容:
开发 OData 服务,将业务数据暴露给消费者
接下来,需要将上图所示的 my.db 数据库中的业务数据,通过 OData 服务,暴露给消费者。
SAP CAP 采用声明式(Declarative)的服务定义方式,将业务数据通过 OData 暴露出来。
在 srv 文件夹下新建一个 cat-service.cds 文件,实现一个图书的目录浏览服务(Catalog Service).
上图 OData 服务源代码一些关键点说明:
使用 using 关键字,导入 db 文件夹下 schema.cds 文件中定义的命名空间 sap.capire.bookshop 下包含的业务模型。
@path 注解,定义了该目录服务的 endpoint 为 /browse.
@readonly 注解,表明该 OData 服务只能以只读的方式,暴露 Books 和 ListOfBooks 数据给消费者。
因为 Books 模型的定义里,没有直接包含书籍的作者名,而是通过一个名为 author 的 Association,指向对应的 Authors 模型。因此,上图第五行,通过 auth.name 后面的 as 关键字,将 Association 指向的作者模型的 name 字段,内联到 OData Books 模型中来。
执行 cds run 命令,启动开发好的 CAP 应用:
http://localhost:4004 访问,就可以测试我们通过以上三个步骤,开发完成的 OData 服务了。
这个由 cds SDK 自动生成的默认界面,提供了很多 OData 服务测试功能。
比如点击 Books 超链接,能通过下面 url 代表的 OData 服务调用,查看到服务器数据库上所有的书籍数据:
http://localhost:4004/browse/Books
点击 Fiori Preview 超链接,能够在一个自动生成的 SAP Fiori Elements 应用里,调用上述 url,将书籍数据展示在 Fiori UI 上。
注意,有朋友按照笔者上述介绍的步骤进行动手练习,遇到如下的错误消息,询问笔者如何解决。
cds run 报错:[ERROR] Cannot find module @sap/cds';,执行命令: npm i -g @sap/cds 重装了,还是不行,请问是什么原因?
首先,如果是使用 -g 选项进行全局安装的话,@sap/cds 会安装在 Node.js 文件夹的 node_modules
文件夹下。在我的机器上,例子如下:
所以首先检查自己 Node.js node_modules 文件夹下的资源,是否和我上图的一致。
然后需要检查 Node.js 的环境变量是否成功设置了。如果本机安装了多个版本的 Node.js,使用 where node
,查看当前命令行的 node 命令,到底调用的是哪一个版本的 node.exe:
我上图的例子说明,虽然我机器安装了 12.18.3 和 16.15.0 两个版本的 Node.js,但是命令行里直接敲 node,调用的是后者。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/af5d12809aaf9cd60df9199f6】。文章转载请联系作者。
评论