SAP產品的Field Extensibility

i042416發表於2018-08-16

SAP開發人員的工作職責,除了實現軟體的功能性需求外,還會花費相當的精力實現一些非功能性需求,來滿足所謂的SAP Product Standard(產品標準)。這些產品標準,包含在SAP專案實施中大顯身手的Extensibility,為客戶業務流程的安全執行保駕護航的Security,也有看起來不太起眼,但實際上體現了SAP作為一家偉大企業所具有的社會擔當的Accessibility,以及Internationalization等等。

今天我們們就來說說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(面向切面程式設計)。

本文會介紹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會自動被高亮。

SAP產品的Field Extensibility

點選高亮區域後,即可看到建立欄位的按鈕。點Create Field進入擴充套件欄位的建立嚮導:

SAP產品的Field Extensibility

這裡需要維護待建立擴充套件欄位的明細資訊,比如欄位標籤,欄位型別,長度,欄位所在的BO模型(下圖的ORDERADM_H)等等。

SAP產品的Field Extensibility

上圖我建立了一個標籤為city name的擴充套件欄位,儲存並啟用後,在UI上顯示如下。

SAP產品的Field Extensibility

這一切步驟僅僅幾分鐘內就可完成,然而背後發生的事情遠遠沒有這麼簡單。為了實現Simple Field Extensibility,SAP開發人員需要進行一系列的開發,我們稱其為Extensibility registration and enablement。這種開發需要SAP Extensibility框架開發人員和SAP應用開發人員雙方共同參與。因為儘管從客戶眼中看到的效果,僅僅是UI新出現了一個擴充套件欄位,然而這只是冰山一角——後臺的資料庫表,BO模型和每一個互動層相關的介面資料結構也應該自動被該擴充套件欄位所增強。

下面是一些例子,我在UI建立的標籤為city name的擴充套件欄位,自動出現在後臺資料庫表中:

SAP產品的Field Extensibility

和CRM Order相關的函式的介面結構也自動包含了這個擴充套件欄位:

SAP產品的Field Extensibility

One Order的BO模型的BTAdminH節點也自動被這個擴充套件欄位增強。

SAP產品的Field Extensibility

那麼Extensibility框架怎麼知道當擴充套件欄位被建立時,這些屬於某個應用程式的資源也需要被增強呢?原來,SAP Extensibility框架開發人員和SAP應用開發人員達成了一個契約:Extensibility框架開發人員定義了一個登錄檔,應用開發人員如果想讓自己負責的UI支援Simple Field Extensibility,需要把自己應用的各種需要被框架自動增強的模型資訊和資料庫表資訊填寫到這個登錄檔裡,這樣當使用者使用AET工具進行增強時,Extensibility框架就知道到底有哪些應用層相關的模型也需要跟著增強。

這個登錄檔的外觀見下圖:

SAP產品的Field Extensibility

除了註冊之外,應用開發人員還有很多其他事情要做,因此SAP內部有個Application Extensibility Guideline的程式設計規範,我們做開發時就是照著這個文件來的。

如果實施夥伴自己開發了一個UI,也想讓其支援Simple Field Extensibility,那麼也需要按照這個Guideline來開發。

我以前做過一個例子供大家參考:

登錄檔的填寫:

https://blogs.sap.com/2013/10/25/step-by-step-to-enable-your-genil-component-with-aet

按照Application Extensibility Guideline讓您的應用支援Simple Field Extensibility

https://blogs.sap.com/2013/10/25/step-by-step-to-enable-your-genil-component-with-aet-part-two/

有的CRM顧問朋友們會不時問我,"為什麼我的AET UI看不到Create Field的按鈕,或者變成灰色了?”其實原因不外乎下面三種:

1. 您的使用者沒有AET使用許可權

2. 您的系統上AET沒有正確setup起來

3. 您選擇的UI不可被AET增強(即UI對應的UI沒有註冊成"可擴充套件”)

在給SAP提incident之前,可以按照我這篇部落格的步驟,自行去除錯找到原因:

https://blogs.sap.com/2013/09/29/inside-aet-why-create-field-button-is-visible-in-some-ui-while-invisible-in-others/

用AET建立的這些擴充套件欄位,在執行時是如何畫到UI上的呢?

簡單地說,CRM WebClient UI的檢視配置資訊(即檢視上需要顯示的欄位明細,欄位間的相對位置,欄位標籤等等),都維護在一個所謂Configuration Context的實體中,以16位的GUID標識。

SAP產品的Field Extensibility

Context內容以XML格式儲存在資料庫表BSP_DL_XMLSTRX2裡。

SAP產品的Field Extensibility

執行時,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產品的Field Extensibility

更多關於擴充套件欄位在執行時的渲染原理講解,請參考我的部落格:

https://blogs.sap.com/2016/12/22/how-extension-field-created-by-aet-is-rendered-in-web-client-ui/

SAP S/4HANA Extensibility

SAP產品的Field Extensibility

和SAP CRM在具體的應用程式UI上直接建立擴充套件欄位稍有不同,S/4HANA透過一個統一的Tile(Custom Fields and Logic)作為入口來建立擴充套件欄位:

SAP產品的Field Extensibility

擴充套件欄位的明細維護介面和SAP CRM的AET工具大同小異。下圖的Business Context指使用者希望這個欄位出現在S/4HANA Fiori應用,Product Master的明細介面的General區域內。

SAP產品的Field Extensibility

擴充套件欄位建立完畢後,客戶進到Product Master明細頁面內,點選右鍵然後從Available Fields列表裡選擇出剛才建立的擴充套件欄位,即可將此擴充套件欄位顯示在Fiori UI上。

SAP產品的Field Extensibility

SAP產品的Field Extensibility

S/4HANA的應用開發人員需要做的事情和前一章節介紹的SAP CRM類似,同樣需要做註冊。

下圖是S/4HANA Extensibility的登錄檔。高亮的一行,代表我在擴充套件欄位建立對話方塊從Business Context下拉選單裡選中的"Product Master General":

SAP產品的Field Extensibility

上述登錄檔針對Product Master General維護了兩個ABAP DDIC include結構,意思是一旦這個擴充套件欄位建立儲存後,會自動出現在這兩個DDIC include結構上。

從登錄檔上方高亮的標籤頁還可看出,在S/4HANA裡透過瀏覽器建立的這些擴充套件欄位,除了直接顯示在Fiori UI之外,還能放到CDS view,OData模型,Web Service,IDoc這些模型中去。登錄檔裡出現的這些選項僅僅表明它們可以支援用Extensibility擴充套件框架新增擴充套件欄位,至於是否真正把擴充套件欄位放進去,由客戶自行決定。透過點選Enable Usage即可將擴充套件欄位新增到對應模型中去。

SAP產品的Field Extensibility

那麼顯示在Fiori UI上的S/4HANA擴充套件欄位,在執行時又是如何被渲染出來的呢?為了回答這個問題,我們先分析當我們把擴充套件欄位新增到Fiori UI時,Fiori UI傳送給S/4HANA後臺的HTTP請求到底包含了哪些資訊。

使用Jerry之前的公眾號文章 Jerry和您聊聊Chrome開發者工具介紹的老套路,用Chrome開發者工具找到這個HTTP請求的明細。請求的payload是一個JSON字串,儲存到本地詳細研究,裡面有7個重要的欄位。

SAP產品的Field Extensibility

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)。

SAP產品的Field Extensibility

在我的例子裡,欄位Price在後設資料中被註解為一個擁有單位的Decimal欄位,其代為欄位為OData模型裡另一個欄位:CurrencyCode。

SAP產品的Field Extensibility

因此在執行時,這個Smart Field會被UI5框架渲染成兩個UI5控制元件,一個控制元件顯示價格的數字, 繫結到OData模型上的欄位Price,另一個控制元件顯示價格單位,繫結到OData模型的欄位CurrencyCode。

SAP產品的Field Extensibility

更多Smart Field和渲染邏輯的講解,請參考我的部落格:

https://blogs.sap.com/2016/03/14/currency-example-how-smart-field-works/

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?請參考我的部落格:

https://blogs.sap.com/2016/05/03/my-understanding-about-how-object-page-in-smart-template-is-rendered/

3. YY1_JDKminimumversionJ_PRD

Fiori UI擴充套件欄位繫結的OData模型的欄位名稱。我們可以做個實驗:在Fiori UI上該擴充套件欄位裡隨便維護一個值,比如"1.7", 然後儲存。關掉UI再重新開啟,很容易在Chrome開發者工具裡觀察到從後臺返回的OData響應結構裡,有一個名為"YY1_JDKminimumversionJ_PRD"的欄位包含了"1.7"這個值。Fiori UI的擴充套件欄位正是繫結到了該模型欄位上,因而能顯示出"1.7"。

SAP產品的Field Extensibility

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命名的由來,一個分層的檔案系統。

SAP產品的Field Extensibility

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: %20002/en-US/ed9aa41c563a44b18701529c8327db4d.html

User layer:儲存personalization資訊,僅對建立該資源的使用者可見。

為什麼要引入這個分層機制呢?還是為了實現文章開頭提到的中心思想:確保合作伙伴和客戶做的增強不會因為SAP的產品升級而丟失。透過內容的分層儲存,SAP,合作伙伴和客戶做的內容彼此隔離,互不影響。在執行時,假設對於同一UI模型,SAP,合作伙伴和客戶均有各自的資源,則終端使用者看到的UI是這些資源的一個並集,我們稱產生這個並集的過程為Merge。在Merge過程中如果遇到衝突,比如一個UI欄位的標籤,SAP,合作伙伴和客戶均有各自的定義,則Merge結果以優先順序最高的layer包含的內容為準。不同layer優先順序從低到高,即上圖report從上到下的layer依次為:

SAP->Partner->Customer->User。

再回到我們正在進行的payload分析。執行report,結果如下。點選按鈕顯示LREP裡這個檔案的完整內容:

SAP產品的Field Extensibility

可以發現該檔案內容就是我們在Chrome開發者工具裡觀察到的從Fiori UI傳送到S/4HANA後臺伺服器的HTTP請求的payload:

SAP產品的Field Extensibility

因此,我們在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來實現檔案內容儲存。

SAP產品的Field Extensibility

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行程式碼。

SAP產品的Field Extensibility

當包含了擴充套件欄位的Fiori UI即將渲染時,首先有一個HTTP請求將待渲染UI包含的所有擴充套件欄位資訊從LREP中讀取出來。注意下圖藍色高亮區域內的/sap/bc/lrep/flex/data, 這就是S/4HANA後臺LREP暴露給Fiori UI的儲存服務。

SAP產品的Field Extensibility

Fiori UI讀取到LREP返回的JSON後,解析到changeType為addFields,於是呼叫Fiori UI框架對應的處理邏輯,根據JSON裡包含的擴充套件欄位明細將其渲染出來。這實際上就是前面提到的,SAP layer的Fiori標準UI同Customer layer的擴充套件欄位的Merge動作。

擴充套件欄位Merge到Fiori UI的入口在AddFields.applyChange:

SAP產品的Field Extensibility

addElementIntoGroupElement會將擴充套件欄位新增到Fiori UI對應的區域內:

SAP產品的Field Extensibility

addElementIntoGroupElement又會呼叫createControl將擴充套件欄位的定義轉換成對應的UI5控制元件例項,後者的Render負責將控制元件例項渲染成原生的HTML程式碼。至此,S/4HANA擴充套件欄位的渲染就完成了。

SAP產品的Field Extensibility

SAP產品的Field Extensibility

要獲取更多Jerry的原創技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:


SAP產品的Field Extensibility

SAP產品的Field Extensibility


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2200191/,如需轉載,請註明出處,否則將追究法律責任。

相關文章