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的擴展字段的建立經過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來開發。
我之前作過一個例子供你們參考:
註冊表的填寫:
按照Application Extensibility Guideline讓您的應用支持Simple Field Extensibility
有的CRM顧問朋友們會不時問我,"爲何個人AET UI看不到Create Field的按鈕,或者變成灰色了?」其實緣由不外乎下面三種:
1. 您的用戶沒有AET使用權限
2. 您的系統上AET沒有正確setup起來
3. 您選擇的UI不可被AET加強(即UI對應的UI沒有註冊成"可擴展」)
在給SAP提incident以前,能夠按照我這篇博客的步驟,自行去調試找到緣由:
用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源代碼裏增長了一個擴展字段對應的節點,以下圖所示:
更多關於擴展字段在運行時的渲染原理講解,請參考個人博客:
和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和渲染邏輯的講解,請參考個人博客:
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?請參考個人博客:
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的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: