在 SAP 云平台的 CloudFoundry 环境下消费 ABAP On-Premise OData 服务

我的前一篇文章 使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数介绍了在 SAP 云平台的 Neo 环境下如何通过 SAP Cloud Connector 消费 ABAP On-Premise 系统里的函数。在那篇文章 demo 程序的 Java 代码里,我们实际是通过 JCO(Java Connector)来远程调用 ABAP On-Premise 系统里的函数。
今天我们换个环境,试试 SAP 云平台的 CloudFoundry 环境。

同时我们也试试换一种方式来消费 ABAP On-Premise 系统的服务。让我们开发一个 Web 应用,通过 OData 的方式显示 ABAP On-Premise 系统里的产品列表及价格信息。
该例子运行效果如下图所示。

同前一篇文章提到的在 SAP 云平台的 Neo 环境里消费 ABAP On-Premise 函数相比,在 CloudFoundry 环境里实现同样的需求,所需的步骤要复杂一些。
同 Neo 环境的部署相比,在 CloudFoundry 环境下最显著的架构区别就是多了个 App Router。为什么 CloudFoundry 环境下需要这个东西?我的同事李贝宁在他的文章 SAP成都研究院李三郎:SCP Application Router简介 里做过详细阐述。
为了完成这个例子,我们需要部署两个应用到 SAP 云平台的 CloudFoundry 环境去,即 App Router 和 Web 应用本身。两个例子的完整代码在我的 github 上:
https://github.com/i042416/CloundFoundry_Connectivity

上图各模块间交互的简单阐述:
1. App Router 作为用户访问 Web 应用的入口。
2. App Router 将请求重定向到 XSUAA 实例,弹出登录界面。该实例负责完成登录认证,稍后会创建它。下图是登录界面在我手机上打开的效果。
3. 登录完成后,App Router 将请求重定向到 Web 应用。
4. Web 应用向 XSUAA 发起两个并行的请求,如图 4a 和 4b 所示,获取用于访问接下来第 5,第 6 步的 JSON Web Token。
5. Web 应用访问 Destination 实例获取对应配置信息。
6. Web 应用将请求发送给 Connectivity 实例。
7. Connectivity 实例将请求通过 Secure tunnel(安全隧道)转发给 Cloud Connector。
8. Cloud Connector 和 On-Premise 系统都位于 Corporate Network 里,直接调用其服务。

明白了原理,下面跟着 Jerry 一起做一做吧。
1. 我前一篇文章 使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数介绍了 Cloud Connector 的下载与安装,因此现在我们可以重用之前安装好的 Cloud Connector。
点击 Add Subaccount 按钮,基于 CloudFoundry Subaccount 创建一个新的配置:

最重要的是维护 CloudFoundry Subaccount 的 ID 和用户名(登录邮箱)。

创建一个从 Virtual Host 到 Internal Host 的映射关系。Virtual Host 的名称可以随便维护,我维护的是 my-backend, 记住这个名称,以后会用到。Internal Host 我维护的是提供 OData 服务的 On-Premise 系统的主机名和端口号。点击 Check 按钮,确保 Cloud Connector 能够成功连接 On-Premise 系统,状态为 Reachable。
将 On-Premise 系统的下列 4 个 ICF 服务路径暴露出来:
/sap/bc/lrep
/sap/iwbep
/sap/opu/odata
/sap/public
至此 Cloud Connector 上的配置完成了。

2. 回顾我们之前介绍的模块交互图,Cloud Connector 上的配置无法直接被部署在 CloudFoundry 上的应用消费。我们还需要在 SAP 云平台上创建三个不同类型的实例。
首先在 SAP 云平台 Cockpit 里创建一个新的 Destination,URL 字段指向前一步 Cloud Connector 里创建的 Virtual Host。这个 Destination 的名称也得记录下来,后面会用到。

进入 Service Marketplace,创建一个新的 XSUAA 实例:

这个 connectivity-jerry-demo 就是稍后我要部署到 SAP 云平台上的 Web 应用名称。

创建好的 XSUAA 实例:

connectivity 和 destination 的实例创建的方式相同,不再赘述。下图是为了完成本文介绍的场景所需的三个不同类型的实例创建好之后的状态截图。

至此 SAP 云平台上的配置也全部完成。
3. 现在开始 Web 应用的开发。先看 App Router 的 xs-app.json: 入口文件是 index.html, 这个 html 文件其实就一行代码:
<a href="/app/">Go to App</a>
点击之后,会跳转到/app/, 而/app/的 route 配置如下,指向 destination "dest-to-app":

而这个 destination 对应的真实 url 维护在 App Router 的 manifest.yml 文件中。同样需要在该 yml 文件的 services 字段里维护前一步创建的 XSUAA 实例:

再看 Web 应用的 manifest.yml 文件:需要将前一步骤依次创建的三种类型的实例名称分别维护如下图所示:

接下来我们需要进行 Web 应用里 UI5 部分的开发,指定产品列表的数据源基于哪一个 OData 服务。在 UI5 的 controller 文件里,指定 OData 模型的路径为相对路径 data-eu。

针对这个相对路径 data-eu,在 neo-app.json 里定义了一个路由,会被重定向到 On-Premise 系统的标准 OData 服务 EPM_REF_APPS_SHOP_SRV。具体重定向到哪个 On-Premise 系统是由路由的 target 字段决定的。在我这个例子里是 jerry-abap-backend, 它就是我们之前在 SAP 云平台 Cockpit 里创建的 Destination。

这个 Destination 的 URL 字段指向 Cloud Connector 的 Virtual host,该 host 又映射到 On-Premise 系统的主机名和端口号。至此大功告成了,SAP Cloud Connector 上的配置,App Router,Web 应用,SAP 云平台上的 connectivity,XSUAA 和 destination 三个实例,这一系列模型犹如一台机器上的一个个零件,协同工作,实现了从 Internet Network 到 Corporate Network 的访问场景。

将两个应用部署到 SAP 云平台的 CloudFoundry 环境去,点击 App Router 作为访问的入口,能看到文章开头的产品列表页面。

并且 Chrome 开发者工具里观察到的网络请求的路径里仅仅包含前文提到的 UI5 应用的 neo-app.json 里配置的路由 data-eu, 而 On-Premise 系统的主机名和端口号并未暴露到 Cloud 环境中。

当然,为了跑这个 demo,您需要在 On-Premise 系统使用事务码/iwfnd/maint_service,为 EPM_REF_APPS_SHOP_SRV 这个标准的 OData 服务指定一个后台系统。在我下图的例子里,该服务的后台实现系统我指定成了 AG3。

在 Java 代码里打印实际的 url,发现是 http://my-backend:80/sap/opu/odata/sap/EPM_REF_APPS_SHOP_SRV/$metadata。

该 url 里的 my-backend:80 会被 Cloud Connector 替换成实际的 On-Premise 系统的地址并发送到 On-Premise 系统去。

要获取更多 Jerry 的原创技术文章,请关注公众号"汪子熙"。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/0e1afa6727681a91dd0ac2436】。文章转载请联系作者。
评论