當前位置:
首頁 > 最新 > SAP產品的Field Extensibility

SAP產品的Field Extensibility

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 ExtensibilityProcess 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會自動被高亮。

點擊高亮區域後,即可看到創建欄位的按鈕。點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來開發。

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

註冊表的填寫:

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的按鈕,或者變成灰色了?」其實原因不外乎下面三種:

您的用戶沒有AET使用許可權

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

您選擇的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標識。

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

運行時,UI框架首先從上述資料庫表裡把XML數據讀出來,解析成DOM, 然後根據DOM里每個節點對應的不同UI控制項類型,實例化不同的UI控制項。比如XML里定義的某個欄位類型為inputfield, 則創建一個CL_THTMLB_INPUTFIELD類的實例。

更多關於擴展欄位在運行時的渲染原理講解,請參考我的博客:

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

SAP S/4HANA Field 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請求到底包含了哪些信息。

表明該擴展欄位在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和渲染邏輯的講解,請參考我的博客:

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

2. id

什麼是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"。

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:https://help.sap.com/viewer/468a97775123488ab3345a0c48cadd8f/1709%20002/en-US/ed9aa41c563a44b18701529c8327db4d.html

User layer:存儲personalization信息,僅對創建該資源的用戶可見。

為什麼要引入這個分層機制呢?還是為了實現文章開頭提到的中心思想:確保Partner和客戶做的增強不會因為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中。

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擴展欄位的渲染就完成了。

為了避免每次用戶打開包含了擴展欄位的Fiori UI時,UI5框架都需要重複執行標準的Smart Template頁面和擴展欄位的Merge過程,UI5設計了一個基於LRU(Least Recently Used)的客戶端緩存。該LRU緩存的實現採用的是HTML5支持的一種本地存儲方案,IndexedDB。這種存儲方案允許在瀏覽器客戶端存儲結構化數據,並提供了高效的支持非同步操作的API。IndexedDB在S/4HANA Fiori UI中的讀寫操作封裝在UI5的庫文件LRUPersistentCache.js中。下圖展示了一個包含了擴展欄位的Fiori UI在渲染時,UI5從本地IndexedDB存儲中讀取之前Merge成功的UI頁面的緩存數據。

從Chrome開發者工具的console頁面能看到Merge好的Fiori UI頁面內容在IndexedDB中的存儲採取的是key-value鍵值對的方式。

IndexedDB提供的一系列get/set API由瀏覽器提供原生實現,其中get接收一個key作為輸入參數,返回對應的值。

這個鍵值對仍舊可以在Chrome開發者工具的Application標籤頁里的IndexedDB區域中查看到。

作為本文的後續,我的同事Boris將會帶來SAP Cloud for Customer的Field Extensibility設計概述。

更多閱讀


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 汪子熙 的精彩文章:

在SAP雲平台的CloudFoundry環境下消費ABAP On-Premise OData服務

TAG:汪子熙 |