30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用
2016年时,Jerry曾经写过一系列关于SAP Fiori Smart Template(现在更名为Fiori Elements了)的博客,介绍了所谓的MDD开发方法论 - Metadata Driven Development,即通过开发维护了对应annotation(注解)的CDS view,结合SAP WebIDE,能够花费最少的编程代价,就能够在短时间内获得一个支持增删改查的Fiori应用。
这个系列的博客集可以在Jerry这篇公众号文章里获得:Jerry的通过CDS view + Smart Template 开发Fiori应用的blog合集。
三年的时间过去了,ABAP在不断向前进化,如今我们有了新的编程模型:Restful ABAP Programming模型,简称为RAP模型。该模型定义了一套架构体系,应用开发人员能够凭借其来高效地进行应用的端到端开发,这种应用具有与生俱来的Restful特质,能充分利用HANA平台的强大计算能力,支持云环境和Fiori UX。
RAP模型的三大支柱:
- Business Service
- Core Data Service
- Behavior Definition
下面请跟着Jerry一起,通过一个实际的例子,了解一下这种全新的通过Restful ABAP Programming模型进行Fiori应用开发的步骤吧。
Jerry还是沿用传统ABAP On-Premises编程培训教材里使用过的经典的SFLIGHT模型来作为底层数据库存储。
(1)首先创建一个数据库表ZTRAVEL_JERRY:(如果想复制这段源代码,请点击文末的“阅读原文”获得)
@EndUserText.label : 'Database table for travel data XXX'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #LIMITED
define table ztravel_jerry {key client : abap.clnt not null;key travel_id : /dmo/travel_id not null;agency_id : /dmo/agency_id;customer_id : /dmo/customer_id;begin_date : /dmo/begin_date;end_date : /dmo/end_date;@Semantics.amount.currencyCode : 'ztravel_jerry.currency_code'booking_fee : /dmo/booking_fee;@Semantics.amount.currencyCode : 'ztravel_jerry.currency_code'total_price : /dmo/total_price;currency_code : /dmo/currency_code;description : /dmo/description;created_by : syuname;created_at : timestampl;last_changed_by : syuname;last_changed_at : timestampl;}
因为我们在ABAP Development Tools里无法用事务码SE16手动往这张表里插入数据,所以我创建一个ABAP类,用ABAP代码往这个表里插入三条数据。
按F9执行这个ABAP类,然后看到三条数据成功插入了:
(2) 我们最终的目的是创建一个支持对这张表进行增删改查的Fiori应用,而Restful ABAP Programming模型的三大支柱之一为Core Data Service,因此我们首先得有基于数据库表ZTRAVEL_JERRY的CDS view.
所以我首先创建一个CDS view:
@AbapCatalog.sqlViewName: 'ZVI_TRAVEL'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Travel data - XXX'
define root view ZI_TRAVEL_JERRYas select from ztravel_jerry as Travel/* Associations */association [0..1] to /DMO/I_Agency as _Agency on $projection.agency_id = _Agency.AgencyIDassociation [0..1] to /DMO/I_Customer as _Customer on $projection.customer_id = _Customer.CustomerIDassociation [0..1] to I_Currency as _Currency on $projection.currency_code = _Currency.Currency{key travel_id,agency_id,customer_id,begin_date,end_date,@Semantics.amount.currencyCode: 'currency_code'booking_fee,@Semantics.amount.currencyCode: 'currency_code'total_price,@Semantics.currencyCode: truecurrency_code,description,/*-- Admin data --*/@Semantics.user.createdBy: truecreated_by,@Semantics.systemDateTime.createdAt: truecreated_at,@Semantics.user.lastChangedBy: truelast_changed_by,@Semantics.systemDateTime.lastChangedAt: truelast_changed_at,/* Public associations */_Agency,_Customer,_Currency
}
然后创建一个projection view,将该view的字段有选择性地暴露出来。
@EndUserText.label: 'Travel projection view - Processor'
@AccessControl.authorizationCheck: #NOT_REQUIRED@UI: {headerInfo: { typeName: 'Travel', typeNamePlural: 'Travels', title: { type: #STANDARD, value: 'TravelID' } } }@Search.searchable: truedefine root view entity ZC_TRAVEL_JERRY as projection on ZI_TRAVEL_JERRY {@UI.facet: [ { id: 'Travel',purpose: #STANDARD,type: #IDENTIFICATION_REFERENCE,label: 'Travel',position: 10 } ]@UI: {lineItem: [ { position: 10, importance: #HIGH } ],identification: [ { position: 10, label: 'Travel ID [1,...,99999999]' } ] }@Search.defaultSearchElement: truekey travel_id as TravelID,@UI: {lineItem: [ { position: 20, importance: #HIGH } ],identification: [ { position: 20 } ],selectionField: [ { position: 20 } ] }@Consumption.valueHelpDefinition: [{ entity : {name: '/DMO/I_Agency', element: 'AgencyID' } }]@ObjectModel.text.element: ['AgencyName'] ----meaning?@Search.defaultSearchElement: trueagency_id as AgencyID, _Agency.Name as AgencyName,@UI: {lineItem: [ { position: 30, importance: #HIGH } ],identification: [ { position: 30 } ],selectionField: [ { position: 30 } ] }@Consumption.valueHelpDefinition: [{ entity : {name: '/DMO/I_Customer', element: 'CustomerID' } }]@ObjectModel.text.element: ['CustomerName']@Search.defaultSearchElement: truecustomer_id as CustomerID,@UI.hidden: true_Customer.LastName as CustomerName,@UI: {lineItem: [ { position: 40, importance: #MEDIUM } ],identification: [ { position: 40 } ] }begin_date as BeginDate,@UI: {lineItem: [ { position: 41, importance: #MEDIUM } ],identification: [ { position: 41 } ] }end_date as EndDate,@UI: {lineItem: [ { position: 50, importance: #MEDIUM } ],identification: [ { position: 50, label: 'Total Price' } ] }@Semantics.amount.currencyCode: 'CurrencyCode'total_price as TotalPrice,@Consumption.valueHelpDefinition: [{entity: {name: 'I_Currency', element: 'Currency' }}]currency_code as CurrencyCode,@UI.identification: [ { position: 60, label: 'Remarks' } ]description as Description,@UI.hidden: truelast_changed_at as LastChangedAt}
大家可以注意到,这个projection view里包含了很多@UI注解,作用和Fiori Elements一样,作为元数据,告诉对应的渲染框架,运行时这些字段应该以什么样的方式渲染在Fiori UI上。
(3) 现在三大支柱之一的Core Data Service已经就位了,接下来我们基于前一步得到的projection view创建Business Service. 选中projection view,右键选择New Service Definition:
这个服务定义的第一条记录,就是通过ABAP expose关键字把projection view ZC_TRAVEL_JERRY暴露出来,模型名称为TravelProcessor:
@EndUserText.label: 'Service Defintion for ZC_Travel_JERRY'
define service ZUI_C_TRAVEL_JERRY {expose ZC_TRAVEL_JERRY as TravelProcessor;expose /DMO/I_Customer as Passenger;expose /DMO/I_Agency as TravelAgency;expose /DMO/I_Airport as Airport;expose I_Currency as Currency;expose I_Country as Country;
}
然后基于这个Service Definition创建一个Service Binding,可以简单把Service Binding理解成Service Definition的一个实例:
Service Binding创建完毕后,点击Activate激活:
之前Service Definition里用expose关键字暴露并指定成的模型TravelProcessor此时就可见了,双击:
双击后会自动打开一个链接,一个Fiori应用就呈现在我们眼前了。我们没有进行一行的JavaScript web编程,就得到了一个专业的支持高级搜索的Fiori应用,能查看底层数据库表ZTRAVEL_JERRY的内容。
(4) 至此我们已经了解了Restful ABAP Programming模型的前两大支柱,还剩下Behavior Definition. 既然RAP的口号是打造具有Restful特性的应用,但到目前为止我们还没有感受到RAP对Restful的支持,这有待Behavior Definition来完成。
选中之前创建的CDS view,创建一个新的Behavior Definition:
实现类型指定为Managed:
我们可以看到这个Behavior Definition的定义里,又多了一些新的ABAP关键字。这个Behavior Definition负责定义底层模型的Transaction Behavior,即代码第18到20行的create,update,delete.
当然增删改查的功能光定义不行,还得创建其对应的实现。上图Definition中已经指定了实现这些行为的ABAP类名称为ZCL_BP_I_TRAVEL_M_JERRY. 为此,右键选择New Behavior Implementation:
创建这个特殊的ABAP实现类:
这个实现类里面也不需要开发人员手动编写代码来完成对底层数据库表的增删改查操作——既然能称之为一个编程模型,那么这些通用的功能都通过框架类CL_ABAP_BEHAVIOR_HANDLER统一完成了,应用开发人员只需要定义一个对该类的声明即可。
把这一步创建好的Behavior Definition模型和其实现全部激活,然后回到我们之前浏览器里打开的Fiori应用,刷新,会发现多了Create和Delete两个按钮,这意味着该应用对创建和删除的支持也已经自动可用了。
同之前的搜索功能一样,这些功能的自动获得,都是建立在应用开发人员一行JavaScript代码都不用编写的基础上的,由此大家感受到了Restful ABAP Programming模型的强大威力了吗?
后续Jerry会继续介绍如何给这个Fiori应用底层使用的模型增添Action和Validation功能,敬请期待。
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用相关推荐
- 如何基于Restful ABAP Programming模型开发并部署一个支持增删改查的Fiori应用
Jerry之前的文章30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用 发布之后,有朋友问我,"没错, 我是在你的文章里看到了Fiori应用的 ...
- Jerry带您了解Restful ABAP Programming模型系列之三:云端ABAP应用调试
Jerry的Restful ABAP Programming模型介绍系列的前两篇文章: 30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用 Jerry带 ...
- Jerry带您了解Restful ABAP Programming模型系列之二:Action和Validation的实现
相信通过Jerry的前一篇文章 30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用,想必大家对Restful ABAP Programming模型已经有 ...
- 使用Cloud Application Programming模型开发OData的一个实际例子
刚刚过去的SAP TechEd上,SAP CTO Juergen Mueller向外界传递了一个重要的信息:身处云时代大环境下的SAP从业者,在SAP云平台上该如何选择适合自己的开发方式? Juerg ...
- mock模拟的数据能增删改查吗_Mock.js模拟数据,脱离后端独立开发,实现增删改查功能...
在目前容近对端手近对端手近对端手近对端手近我们的生产实际中,后端的接口往往是较晚才会出来,并且还要写接口文档,于是我们的前端的许多开发都要等到接口给我们才能进行,这样对于我们前端来说显得十分的被动,于 ...
- 微信小程序云开发.云数据库.增删改查SDK
首页头部模块 海报轮播模块 球队导航模块 NBA新闻 网络API接口,用wx.request请求,成功后用setData接收数据,在wxml中用wx.for循环输出 自定义组件 即自定义标签 定义后在 ...
- 巨杉数据库SequoiaDB在Java开发中的增删改查CURD
文章目录 JSON应用开发 增删改查操作 1 快速入门 1.1 环境部署 部署SequoiaDB集群环境 部署Windows开发环境 1.2 正式开始 2 CURD教程 2.1 Java开发环境搭建 ...
- android增删功能代码,Android Studio开发实战 之 增删改查
增删改查是一个应用最基础的操作,增删改查的流程走通了,下面的路程也就顺利多了.现在使用Android Studio开发一个简单的应用,该应用就实现了增删改查的操作,看似简单,到底简不简单呢,下面开始操 ...
- php加数据库开发案例,PHP简单数据库操作类实例【支持增删改查及链式操作】
本文实例讲述了PHP简单数据库操作类.分享给大家供大家参考,具体如下: 在进行项目开发时,数据库是必不可少的东西了.但是很多时候却又对数据库SQL语句的繁杂而感到头疼.提供一个我自己使用的数据库操作类 ...
最新文章
- [转]VS2015编译的程序在其他机器上缺少msvcp120.dll
- 一文详述Attention最新进展
- 世园会开幕式上的机器人_【在国际智能制造大会暨智能机器人大会开幕式上的致辞】世界智能机器人大会...
- c# 串口最简单接收十六进制
- TCP长连接与短连接的区别(转)
- 实验7.2 二维数组 7-5 打印杨辉三角
- 关于优酷开放SDk之setOnVideoIndexUpdateListener
- Andorid之MediaPlayer和AudioTrack播放Audio的区别与联系
- 语音对话系统的设计要点与多轮对话的重要性
- tair client java_TFS(Taobao File System)Java Client 使用经验
- 利用cookie的跨域单点登录的简单实现
- mysql 当前时间戳_kettle教程-mysql数据增量抽取-无需时间戳无需标识
- 判断浏览器是否为IE和版本
- mysql的本地id可以随便设置马_Mysql主从复制原理及搭建
- linux负载均衡总结性说明(四层负载/七层负载)
- uniapp switch按钮的使用开关按钮效果demo(整理)
- Java+Springmvc+velement实现高校学科竞赛项目系统+Lw
- 三阶魔方层先还原方法图解2
- 三神器-迭代器、生成器和装饰器
- 小米手机短信拦截转发失败原因