SAP产品的Field Extensibility

SAP开发人员的工做职责,除了实现软件的功能性需求外,还会花费至关的精力实现一些非功能性需求,来知足所谓的SAP Product Standard(产品标准)。这些产品标准,包含在SAP项目实施中大显身手的Extensibility,为客户业务流程的安全运行保驾护航的Security,也有看起来不太起眼,但实际上体现了SAP做为一家伟大企业所具备的社会担当的Accessibility,以及Internationalization等等。html

今天我们就来讲说SAP产品的Extensibility。尽管SAP产品对现实世界中的业务流程作了必定程度的抽象,可是部分客户在实际使用过程当中仍然会发现本身企业有些特殊的业务流程没法用SAP产品的标准功能来支持。此时SAP产品的Extensibility就有了用武之地:所谓Extensibility,即SAP产品的底层框架提供了足够的灵活性,确保客户和实施伙伴借助SAP提供的标准工具,可以对SAP产品进行加强(Enhancement),以此来知足本身特殊的业务需求。这种加强和直接修改SAP产品(Modification)的区别在于,前者是SAP推荐的方式,加强实现自己和被加强的SAP标准资源是不一样的实体,分别存储于不一样的包内。每次版本升级时,加强实现自己不会受到任何影响;而修改,则改动了SAP产品的标准代码或模型,每次版本升级这些修改都会所有丢失掉。并且在基于Netweaver的Cloud产品里,好比S/4HANA Cloud和SAP Cloud for Customer,客户和实施伙伴没有任何途径直接去修改Netweaver后台的资源。前端

SAP产品的Extensibility分为Field Extensibility和Process Extensibility。Field Extensibility,即用户可直接在浏览器里,经过简单的步骤在UI上指望的区域建立新的字段,咱们称其为扩展字段(Extension Field)。有时候咱们又会在这个术语前加上Simple的前缀,这个前缀强调,客户在建立新字段时,既不须要具有任何技术知识,也不须要了解该产品底层的数据模型的设计细节,而是经过相似咱们在Windows系统下安装软件的向导同样,经过向导提示的简单步骤便可完成。Process Extensibility,强调流程的加强,即经过SAP提供的加强工具,好比Business Add-In(BAdI), Post-Exit等等,对SAP产品的标准流程作必定程度的加强。没有接触过BAdI和Post-Exit的朋友们,若是作过Java Spring开发,能够把BAdI类比成Spring里各类各样的hook,把Post-Exit类比成Spring AOP(面向切面编程)。web

本文会介绍SAP CRM和S/4HANA的Field Extensibility。本文的后续,SAP Cloud for Customer(C4C)的Field Extensibility,会由Jerry的同事,SAP成都研究院C4C开发团队的Boris来介绍。数据库

SAP CRM Field Extensibility

SAP CRM的扩展字段的建立经过Application Enhancement Tool(AET)这个工具完成。用户在建立扩展字段以前,先要进入配置模式(Configuration mode),而后能够进行扩展字段建立的UI会自动被高亮。编程

点击高亮区域后,便可看到建立字段的按钮。点Create Field进入扩展字段的建立向导:浏览器

这里须要维护待建立扩展字段的明细信息,好比字段标签,字段类型,长度,字段所在的BO模型(下图的ORDERADM_H)等等。安全

上图我建立了一个标签为city name的扩展字段,保存并激活后,在UI上显示以下。服务器

这一切步骤仅仅几分钟内就可完成,然而背后发生的事情远远没有这么简单。为了实现Simple Field Extensibility,SAP开发人员须要进行一系列的开发,咱们称其为Extensibility registration and enablement。这种开发须要SAP Extensibility框架开发人员和SAP应用开发人员双方共同参与。由于尽管从客户眼中看到的效果,仅仅是UI新出现了一个扩展字段,然而这只是冰山一角——后台的数据库表,BO模型和每个交互层相关的接口数据结构也应该自动被该扩展字段所加强。数据结构

下面是一些例子,我在UI建立的标签为city name的扩展字段,自动出如今后台数据库表中:架构

和CRM Order相关的函数的接口结构也自动包含了这个扩展字段:

One Order的BO模型的BTAdminH节点也自动被这个扩展字段加强。

那么Extensibility框架怎么知道当扩展字段被建立时,这些属于某个应用程序的资源也须要被加强呢?原来,SAP Extensibility框架开发人员和SAP应用开发人员达成了一个契约:Extensibility框架开发人员定义了一个注册表,应用开发人员若是想让本身负责的UI支持Simple Field Extensibility,须要把本身应用的各类须要被框架自动加强的模型信息和数据库表信息填写到这个注册表里,这样当用户使用AET工具进行加强时,Extensibility框架就知道到底有哪些应用层相关的模型也须要跟着加强。

这个注册表的外观见下图:

除了注册以外,应用开发人员还有不少其余事情要作,所以SAP内部有个Application Extensibility Guideline的编程规范,咱们作开发时就是照着这个文档来的。

若是实施伙伴本身开发了一个UI,也想让其支持Simple Field Extensibility,那么也须要按照这个Guideline来开发。

我之前作过一个例子供你们参考:

注册表的填写:

blogs.sap.com/2013/10/25/…

按照Application Extensibility Guideline让您的应用支持Simple Field Extensibility

blogs.sap.com/2013/10/25/…

有的CRM顾问朋友们会不时问我,"为何个人AET UI看不到Create Field的按钮,或者变成灰色了?”其实缘由不外乎下面三种:

1. 您的用户没有AET使用权限

2. 您的系统上AET没有正确setup起来

3. 您选择的UI不可被AET加强(即UI对应的UI没有注册成"可扩展”)

在给SAP提incident以前,能够按照我这篇博客的步骤,自行去调试找到缘由:

blogs.sap.com/2013/09/29/…

用AET建立的这些扩展字段,在运行时是如何画到UI上的呢?

简单地说,CRM WebClient UI的视图配置信息(即视图上须要显示的字段明细,字段间的相对位置,字段标签等等),都维护在一个所谓Configuration Context的实体中,以16位的GUID标识。

Context内容以XML格式存储在数据库表BSP_DL_XMLSTRX2里。

运行时,UI框架首先从上述数据库表里把XML数据读出来,解析成DOM, 而后根据DOM里每一个节点对应的不一样UI控件类型,实例化不一样的UI控件。好比XML里定义的某个字段类型为inputfield, 则建立一个CL_THTMLB_INPUTFIELD类的实例。Jerry在以前的公众号文章SAP UI和Salesforce UI开发漫谈介绍过,每一个WebClient UI支持的控件都会有一个相似SAP UI5中的Render类,负责生成该控件对应的原生HTML代码。而将AET建立出来的扩展字段添加到UI上,从UI视图配置的角度讲,仅仅是在XML源代码里增长了一个扩展字段对应的节点,以下图所示:

更多关于扩展字段在运行时的渲染原理讲解,请参考个人博客:

blogs.sap.com/2016/12/22/…

SAP S/4HANA Extensibility

和SAP CRM在具体的应用程序UI上直接建立扩展字段稍有不一样,S/4HANA经过一个统一的Tile(Custom Fields and Logic)做为入口来建立扩展字段:

扩展字段的明细维护界面和SAP CRM的AET工具大同小异。下图的Business Context指用户但愿这个字段出如今S/4HANA Fiori应用,Product Master的明细界面的General区域内。

扩展字段建立完毕后,客户进到Product Master明细页面内,点击右键而后从Available Fields列表里选择出刚才建立的扩展字段,便可将此扩展字段显示在Fiori UI上。

S/4HANA的应用开发人员须要作的事情和前一章节介绍的SAP CRM相似,一样须要作注册。

下图是S/4HANA Extensibility的注册表。高亮的一行,表明我在扩展字段建立对话框从Business Context下拉菜单里选中的"Product Master General":

上述注册表针对Product Master General维护了两个ABAP DDIC include结构,意思是一旦这个扩展字段建立保存后,会自动出如今这两个DDIC include结构上。

从注册表上方高亮的标签页还可看出,在S/4HANA里经过浏览器建立的这些扩展字段,除了直接显示在Fiori UI以外,还能放到CDS view,OData模型,Web Service,IDoc这些模型中去。注册表里出现的这些选项仅仅代表它们能够支持用Extensibility扩展框架添加扩展字段,至因而否真正把扩展字段放进去,由客户自行决定。经过点击Enable Usage便可将扩展字段添加到对应模型中去。

那么显示在Fiori UI上的S/4HANA扩展字段,在运行时又是如何被渲染出来的呢?为了回答这个问题,咱们先分析当咱们把扩展字段添加到Fiori UI时,Fiori UI发送给S/4HANA后台的HTTP请求到底包含了哪些信息。

使用Jerry以前的公众号文章 Jerry和您聊聊Chrome开发者工具介绍的老套路,用Chrome开发者工具找到这个HTTP请求的明细。请求的payload是一个JSON字符串,保存到本地详细研究,里面有7个重要的字段。

1. jstype: sap.ui.comp.smartfield.SmartField

代表该扩展字段在Fiori UI视图中的实现类型为Smart Field。什么是Smart Field?它也是UI5提供的控件之一,但和sap.m.Button, sap.m.Input这些拥有具体类型的UI控件不一样,Smart Field在XML视图开发阶段,并无和任何肯定的UI显示类型绑定,实际上只是一个占位符。下图是一个Smart Field的例子,仅仅凭借这个XML视图片断,咱们根本不知道id为idPrice的Smart Field,在运行时到底会被渲染成一个什么样的UI5控件。相反,该控件的类型,在运行时才能决定下来,取决于其绑定的字段Price在OData模型的元数据中具备何种注解(annotation)。

在个人例子里,字段Price在元数据中被注解为一个拥有单位的Decimal字段,其代为字段为OData模型里另外一个字段:CurrencyCode。

所以在运行时,这个Smart Field会被UI5框架渲染成两个UI5控件,一个控件显示价格的数字, 绑定到OData模型上的字段Price,另外一个控件显示价格单位,绑定到OData模型的字段CurrencyCode。

更多Smart Field和渲染逻辑的讲解,请参考个人博客:

blogs.sap.com/2016/03/14/…

2. id:mdm.cmd.product.maintain::sap.suite.ui.generic.template.ObjectPage.view.Detail::C_Product...

代表了该扩展字段到底添加到哪一个Fiori应用的哪个具体UI区域。ID前半部分的mdm.cmd.product.maintain表明S/4HANA Product Master这个Fiori应用,sap.suite.ui.generic.template.ObjectPage.view.Detail表明这个Fiori应用是基于SAP Smart Template框架构建而成,扩展字段所在的UI基于Smart Template的ObjectPage的Detail页面构建。

什么是Smart Template的ObjectPage?请参考个人博客:

blogs.sap.com/2016/05/03/…

3. YY1_JDKminimumversionJ_PRD

Fiori UI扩展字段绑定的OData模型的字段名称。咱们能够作个实验:在Fiori UI上该扩展字段里随便维护一个值,好比"1.7", 而后保存。关掉UI再从新打开,很容易在Chrome开发者工具里观察到从后台返回的OData响应结构里,有一个名为"YY1_JDKminimumversionJ_PRD"的字段包含了"1.7"这个值。Fiori UI的扩展字段正是绑定到了该模型字段上,于是能显示出"1.7"。

4. fileName

5. layer:CUSTOMER,packageName:$tmp

这几个字段须要联合起来解释。前面CRM章节已经介绍过,SAP CRM WebClient UI视图的配置信息,以XML的格式维护在后台数据库表中。然而S/4HANA Fiori应用由于基于UI5开发,不存在这种配置信息对应的存储数据库表,而是用文件的方式,把扩展字段和Fiori UI的对应关系存储起来,放到一个特殊的仓库里。文件的内容大致上就是我如今正在介绍的从Chrome开发者工具里观察到的JSON字符串,文件存储的区域称为LREP(Layered Repository)。LREP实际是ABAP实现的一个文件系统,能够用report /UIF/GET_CHANGES_4_TARGET浏览其内容。

执行report,最醒目的就是这几个layer,这也是LREP命名的由来,一个分层的文件系统。

Vendor layer:即SAP layer,包含SAP发布的标准内容。

Partner layer:Partner能够基于SAP layer的内容作加强。例如同CRM AET同样,Partner的加强能够经过配置放到一个能够传输的ABAP包里,那么Partner在Fiori UI上建立的扩展字段均存储在这个ABAP包内,从开发系统传到测试和生产系统。

Customer layer:客户经过S/4HANA的扩展工具作的加强,通常都配置为存储于$tmp包内,不可传输,对同一系统的其余全部用户都可见。

Draft layer:和本文主题无关,用于S/4HANA的Draft概念处理,参考SAP help:help.sap.com/viewer/468a…

User layer:存储personalization信息,仅对建立该资源的用户可见。

为何要引入这个分层机制呢?仍是为了实现文章开头提到的中心思想:确保合做伙伴和客户作的加强不会由于SAP的产品升级而丢失。经过内容的分层存储,SAP,合做伙伴和客户作的内容彼此隔离,互不影响。在运行时,假设对于同一UI模型,SAP,合做伙伴和客户均有各自的资源,则最终用户看到的UI是这些资源的一个并集,咱们称产生这个并集的过程为Merge。在Merge过程当中若是遇到冲突,好比一个UI字段的标签,SAP,合做伙伴和客户均有各自的定义,则Merge结果以优先级最高的layer包含的内容为准。不一样layer优先级从低到高,即上图report从上到下的layer依次为:

SAP->Partner->Customer->User。

再回到咱们正在进行的payload分析。执行report,结果以下。点击按钮显示LREP里这个文件的完整内容:

能够发现该文件内容就是咱们在Chrome开发者工具里观察到的从Fiori UI发送到S/4HANA后台服务器的HTTP请求的payload:

所以,咱们在Fiori UI从右键菜单的Available Fields里选择扩展字段放到Fiori UI上时,Fiori UI经过HTTP请求将该扩展字段的明细,即包含了迄今为止咱们分析的这几个字段的JSON字符串发送到S/4HANA后台,存储在LREP中。

Fiori UI与S/4HANA LREP的交互经过sap.ui.fl.LrepConnector.js完成,由后者调用LREP暴露出来的service来实现文件内容存储。

6. reference: mdm.cmd.product.maintain.Component

Product Master这个Fiori应用的Component ID,能够在BSP应用MD_PROD_MAS_S1的Component.js里找到。前面说过了,Product Master这个Fiori应用基于Smart Template构建,并无本身的前端实现,所以Component.js只是一个wrapper,仅有不到6行代码。

当包含了扩展字段的Fiori UI即将渲染时,首先有一个HTTP请求将待渲染UI包含的全部扩展字段信息从LREP中读取出来。注意下图蓝色高亮区域内的/sap/bc/lrep/flex/data, 这就是S/4HANA后台LREP暴露给Fiori UI的存储服务。

Fiori UI读取到LREP返回的JSON后,解析到changeType为addFields,因而调用Fiori UI框架对应的处理逻辑,根据JSON里包含的扩展字段明细将其渲染出来。这实际上就是前面提到的,SAP layer的Fiori标准UI同Customer layer的扩展字段的Merge动做。

扩展字段Merge到Fiori UI的入口在AddFields.applyChange:

addElementIntoGroupElement会将扩展字段添加到Fiori UI对应的区域内:

addElementIntoGroupElement又会调用createControl将扩展字段的定义转换成对应的UI5控件实例,后者的Render负责将控件实例渲染成原生的HTML代码。至此,S/4HANA扩展字段的渲染就完成了。

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

相关文章
相关标签/搜索