Week2
划重点:projection view是用来暴露服务需要的字段和entity。包括底层数据模型的反规范化。如输入帮助、搜索之类的微调和定义Ul annotation。
Unit1
从建表开始开发一个只读的报表App,这也是最常见的一种需求场景。
大的步骤也就是下面几个单元的标题
创建数据库表–>创建CDS View–>定义CDS数据模型的Projection–>完善UI 元素–>创建OData UI服务–>添加基本权限控制
开发流程:
所用到的数据模型:
完成后的效果:
Unit2 Creating the Database Tables
- 首先,创建一个subpackage
- 创建数据库表
ZRAP_ATRAV_1132
和ZRAP_ABOOK_1132
和GUI建表没有太大区别,定义主键和普通字段,只不过使用描述性语句@Semantics.amount.currencyCode:
定义参考字段。
创建一个类来插入一些demo数据
这里用了一个内置函数uuid( )
来生成主键 Travel_uuid,其它没什么特别的。
Unit3 Creating the CDS Data Model
介绍CDS的特性
本节要创建一个复合BO,这个BO由 Travel 做为根BO(root)和 Booking做为子BO(Child)组成。
定义CDS View Entity,CDS View Entity和DDIC-base CDS View的区别是前者没有关联的SQL View,前者是后者的继承者,在Lifecycle方面有很多改善,不像后者在创建的同时会有一个SQL View被创建。
首先创建基本BO视图,然后定义哪个是Root node哪个是Child node
几点需要说明:
- 因为这是两个新建的CDSView Entity相互Association,所以要一起激活。
- 另外上面一些Semantics是为了下一周的behavior做准备的,后面再讨论具体应用。
- 通过association关系可以看到1条travel记录可能对应多条booking记录。
- 在声明视图字段的同时将association一同声明了出来
- 此时view声明出来的字段已经有了alias,这样的好处是方便阅读的同时隐藏真实字段名
- CDS View激活成功,但有warning信息,原因是我们声明了
@AccessControl.authorizationCheck: #CHECK
但却没有定义访问控制,这个会在unit7中创建。
接下来修改刚创建好的视图关键字来明确BO间的结构关系,我们要把Travel定义为Root node,Booking定义为Child node.
修改Travel CDS View Entity:
define view entity ZI_RAP_Travel_1132
改为define root view entity ZI_RAP_Travel_1132
association [0..*] to ZI_RAP_Booking_1132
改为composition [0..*] to ZI_RAP_Booking_1132
修改Booking CDS View Entity:
association [1..1] to ZI_RAP_TRAVEL_1132
association to parent ZI_RAP_Travel_1132
然后同时激活
Unit4 Defining the CDS Data Model Projection
基于cds的数据模型投影(projection),它允许反规范化和丰富底层数据模型。可以用额外的数据或是一些与消费和对象结构相关的元数据来丰富它。通俗来讲,Projection可以理解为我们将模型中哪些东西以什么样的形式暴露出来。
本节要实现的内容有:
- 创建两个projection View,Travel projection view和Booking projection view. 并且会启用用于全文检索的projection并且指定将要用户自由检索的元素。
- 使用annotations
@Search
来允许使用另一个单独的文件对当前projection View进行自由修改增强以扩展metadata,简称MDEs。
这样的好处是它可以将与业务对象相关的annotation分离在一个单独的文件中。 - 在projection list中增强字段
Agency_Name
,customer_Name
,Carrier_Name
,和一个使用annotation@ObjectModel
拼接的单位文本字段。 - 使用
@Consumption
给下面几上字段添加搜索帮助Agency ID
,Customer ID
,Carrier ID
。 - 可以导航到BO projection 层相关的entity中。
我们前面定义的业务对象结构是与服务无关的,用于一般用途。意思是这一节使用了projection view来暴露服务需要的字段和entity。包括底层数据模型的反规范化。如输入帮助、搜索之类的微调和Ul annotation。
Consumption View的命名规范:ZC_*
默认会将Travel CDS View entity的所有字段和Associationg带出来
几点说明:
- Alias
'Travel'
是为当前projection view指定的别名。 - 关键字
root
声明了这是一个Root node。 @Metadata.allowedExtension
新增的这个annotation,允许以单独文件的形式扩展metadata。@Search.Searchable
,允许Full-text检索,也就是自由搜索。@Search.DefaultSearchElement
,TravelID
,AgencyID
,CustomerID
这三个元素使用了这个annotation来开启freestyle search。AgencyName
CustomerName
通过使用@ObjectModel.text
被指定为元素AgencyID
和CustomerID
的文本描述。也就是元素注释。@Consumption.valueHelpDefinition
为元素AgencyID
、CustomerID
和CurrencyCode
指定输入帮助,指定充当值输入帮助提供者的目标CDS entity的名称和链接到本地元素的元素名称。如@Consumption.valueHelpDefinition: [{ entity: { name: '/DMO/I_Customer', element: 'CustomerID'} }]
- 元素
CreatedBy
,CreatedAt
LastChangedBy
从projection view中拿掉了,因为它们不需要在这个场景中的服务所使用。 - Projection view中同时暴露了Association。
10.到子节点_Booking
的association使用了关键字redirected to composition child
。
这时候报错,因为子节点还没有创建,和上面的CDS view entity创建时一样,留在后面一起激活。
接下来创建Projection View Booking
几点说明:
- 除了和创建 Travel Projection View一样使用了几个annotation外,child node的区别是使用了
redirected to parent
来区别这是一个指向了上级node的child nod.
然后把两个projection view一起激活。
Unit5 Enriching the Projected Data Model with UI Metadata
这一节是在上一节的基础上创建一个Metadata的Extension文件,前提是上一节定义Projection View时要有一个声明@Metadata.allowExtensions:true
在Consumption View的基础上创建Metadata Extension
默认会放一个dummy元素,删掉它然后使用Content Assistent(默认快捷键 alt + /)插入所有元素,然后删除掉associations以及AgencyName
,CustomerName
,以及CurrencyCode
,因为它们已经做为其它元素的annotation出现了,这里不需要对它们进行UI增强。
接下来就可以对各个元素进行UI annotation extension
几点说明 :
1.@Metadata.layer: #CORE
,这里的#CORE
是因为针对一个CDS Entity可以有多个Extension文件,那怎么确定它们的优先级呢,就是使用这个Layer来确定,优先级#CORE
最低,优先级 #CUSTOMER
最高。
2. 在ANNOTATE VIEW
之前的@UI
是用来声明标题信息的,比如类型名称和标题,以及变式,比如默认的排序。
3. @UI.facet: [ { id: 'Travel',...
这一段,声明了对象页面及其布局的导航。travel对象页面有两个Facet: 标签页的名称分别是’Travel‘ 和’Booking‘,位置10和20, 类型分别是 travel实体的标识引用(#IDENTIFICATION_REFERENCE) 和 Booking实体的行项目引用(#LINEITEM_REFERENCE)–使用assocition_Booking
指定为目标元素。
4. 各种@UI
annotation用于指定应用页面上每个元素的布局,比如,
@UI.lineItem
指定了当前元素在list中作为一列出现的位置,
@UI.identification
用来指定在Idenfication页面的位置,
@UI.selectionField
声明了这是一个filter bar中出现的可以过滤数据的字段,如果有输入帮助定义在这个元素上,那么在UI上也可以自动出现,
@UI.hidden:true
用来隐藏元素,
具体使用方案参考Defining CDS Annotations for Metadata-Driven UIs 和the UI Annotations supported in ABAP CDS can be found
Unit6 Creating and Previewing the OData UI Service
本节就要正式定义OData UI服务了,也就是创建一个 服务定义(Service definition) 来指定OData服务的scope,然后创建一个服务绑定(Service binding),将这个服务和 OData 协议以UI服务的形式进行绑定。
定义服务的scope是通过暴露相关CDS View完成的,然后它们的metadata以及behavior就会自动暴露出去,
首先在消费视图的基础上创建Service Definition
默认会放一个dummy entity,删除,写上我们将要暴露相关的entity
这里的entity有的是显示UI元素数据的,有的是用来做输入帮助用的。激活
然后创建Service Binding
这里就指定了当前的是服务是一个什么类型的服务,还记得第一周介绍的服务消费类型的这张图吧,不同的消费类型提供不同的特性
激活后进行服务发布
然后在右下的位置会看到这个服务的一些信息,比如包含的哪些entity以及还可以看到它有哪些behavior,可以点击preview进行预览,或者点击
此时的Full-text检索,以及值的输入帮助,以及Filter条件等功能都是可用的,并且可以点击行项目进行到详细页
Unit7 Implementing Basic Authorizations
本节通过创建CDS Roles 和权限对象加入一些基本的权限控制。
正如上周提到的,ABAP CDS提供了Data Control Language(DCL),用于使用CDS Roles定义对数据的授权访问。ABAP平台上使用的传统的权限检查方法要求对所选数据进行显式的编码权限检查。它存储在应用层的内部表里。但CDS DCL提供了一种基于隐式权限检查的声明式方法,这种检查只有在尝试访问CDS Entity时发生。可以使用PFCG条件,固定值条件、用户条件和继承条件来定义CDS Role。
必须为每个CDS实体明确定义它们。它们是数据模型的一部分,因此也被下推到数据库层,以便在读取CDS数据模型时只返回经过授权的数据。CDS角色只定义一次就可以在访问这个实体时自动使用。
这里,要定义一个权限对象和Travel Entity的两个CDS Role,一个在数据建模层,另一个位于数据模型projection的业务服务供应层。
数据建模层的CDS role将会使用固定值和PFCG Condition定义,我们将为此创建一个权限对象。最后,第二个CDS角色将继承底层的条件。(如下图)
首先创建一个数据元素
然后创建一个权限字段
然后创建权限对象
手工添加允许的Activities,保存后会自动填入Object Class为CPAE。
接下来创建 CDS Role
在CDS View Entity的基础上创建Access control
激活后再预览CDS View Entity来验证一下
可以发现现在取到的数据的CurrencyCode全是’EUR’。
接下来尝试加入刚刚创建的传统的权限对象ZOSTAT1132
然后再预览会发现没有数据可以显示,因为我当前用户没有这个权限对象的权限。
这时如果预览Projection View时,或是使用Fiori预览服务的entity时,数据是不受任何影响的,因为我们还没有为projection view ZC_RAP_TRAVEL_1132
定义访问规则。
必须为每个CDS实体(CDS View Entity或Projection View是不同类型的实体)显式地定义CDS访问控制(又名CDS role)。访问规则没有隐式继承,也就是说Projection View不会自动继承CDS View Entity的CDS role。
接下来要为Projection View创建 CDS Role
与ZI_RAP_TRAVEL_1132不同的是模版使用的是Define Role with inherited Condition
改一下${cds_source_entity}
几点说明:
@MappingRole:true
用来分配CDS role到每一个用户中,不区别Clientinheriting conditions from entity
指定了从哪个Entity中继承Access control
这时再预览这个projection view时就和ZI_RAP_TRAVEL_1132预览一样了。
临时禁用CDS Role的办法:
注释权限检查语句,用true;
来代替。
至此,第二周结束。已经可以创建一个带有权限控制的只读应用