Eine häufige Anforderung bei der SAPUI5 Entwicklung ist der Umgang mit den zahlreichen Schlüsseln, die im ERP Backend verwendet werden. Zu so einem Schlüssel muss durch die SAPUI5 App die Bedeutung angezeigt werden. In diesem Blog-Artikel entwickeln wir einen Function Import, welcher die NameValue-Paare für Dömänenfestwerte an die SAPUI5 App zurückliefert.
Domänenfestwerte im SAP DDIC
Ein Beispiel für Domänenfestwerte ist der Lebenszyklusstatus einer SalesOrder im EPM Model. Dies ist das Tabellenfeld SNWD_SO-LIFECYCLE_STATUS.
Die möglichen Werte des Status sind definiert durch die Domäne D_SO_LC.
Im SAP DDIC sind diese Werte sprachabhängig in Tabelle DD07T gespeichert.
Starten wir mit der Implementierung. Die Implementierung besteht aus den folgenden Schritten:
- Modellierung des komplexen Typen NameValue
- Modellierung des Function Imports getDomFixValues
- Implementierung des Function Imports getDomFixValues
- Test des Function Imports im Gateway Client
- Integration in die Fiori App
1. Modellierung des komplexen Typen NameValue
Der komplexe Typ NameValue besteht aus den beiden String-Feldern Name und Value. Diese Struktur enthält den Schlüssel aus DD07T~DOMVALUE_L sowie die Bedeutung des Schlüssels aus DD07T~DDTEXT. Zur Typisierung benutze ich die ABAP-Struktur /IWBEP/S_MGW_NAME_VALUE_PAIR.
2. Modellierung des Function Imports getDomFixValues
Der Function Import getDomFixValues erhält als Url Parameter den Namen der Domäne und liefert eine Tabelle des komplexen Typ NameValue zurück.
3. Implementierung des Function Imports getDomFixValues
Nach der Generierung der Laufzeitobjekte kann der Function Import implementiert werden. Das Gateway Projekt habe ich in diesem Beispiel ZRL_DOMFIXVALUE genannt. Die generierte Data Provider Class heißt also ZCL_ZRL_DOMFIXVALUE_DPC_EXT. Für die Implementierung des Function Imports reimplementiere ich die Methode /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION.
Zur besseren Strukturierung des Codes deligiere ich die Ausführung an die private Methode FCT_GET_DOM_FIX_VALUES.
Die Methode FCT_GET_DOM_FIX_VALUES enthält die eigentliche Logik. Mit dem Namen der Domäne lese ich die Tabelle DD07T. Der Parameter des Function Imports ist über die Struktur zcl_zrl_domfixvalue_mpc=>ts_getdomfixvalues benutzbar. Für den Complex Type NameValue wird in der der Model Provider Class der Typ zcl_zrl_domfixvalue_mpc=>NameValue generiert.
* ---------------------------------------------------------------------------------------+ * | Instance Private Method ZCL_ZRL_DOMFIXVALUE_DPC_EXT->FCT_GET_DOM_FIX_VALUES * +-------------------------------------------------------------------------------------------------+ * | [--->] IR_FUNC_IMPORT TYPE REF TO /IWBEP/IF_MGW_REQ_FUNC_IMPORT * | [<---] ER_DATA TYPE REF TO DATA * | [!CX!] /IWBEP/CX_MGW_BUSI_EXCEPTION * +-------------------------------------------------------------------------------------- METHOD fct_get_dom_fix_values. DATA lt_keyvalue TYPE TABLE OF zcl_zrl_domfixvalue_mpc=>keyvalue. DATA ls_param TYPE zcl_zrl_domfixvalue_mpc=>ts_getdomfixvalues. ir_func_import->get_converted_parameters( IMPORTING es_parameter_values = ls_param ). SELECT dd07t~domvalue_l AS key dd07t~ddtext AS value FROM dd07t INTO TABLE lt_keyvalue WHERE dd07t~domname = ls_param-domname AND dd07t~ddlanguage = sy-langu AND dd07t~as4local = 'A' AND dd07t~as4vers = '0000'. IF sy-subrc <> 0. RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING message = |FCT_GET_DOM_FIX_VALUES: No domain fix values found for { ls_param-domname } |. ENDIF. copy_data_to_ref( EXPORTING is_data = lt_keyvalue CHANGING cr_data = er_data ). ENDMETHOD. * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_ZRL_DOMFIXVALUE_DPC_EXT->/IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_ACTION_NAME TYPE STRING(optional) * | [--->] IT_PARAMETER TYPE /IWBEP/T_MGW_NAME_VALUE_PAIR(optional) * | [--->] IO_TECH_REQUEST_CONTEXT TYPE REF TO /IWBEP/IF_MGW_REQ_FUNC_IMPORT(optional) * | [<---] ER_DATA TYPE REF TO DATA * | [!CX!] /IWBEP/CX_MGW_BUSI_EXCEPTION * | [!CX!] /IWBEP/CX_MGW_TECH_EXCEPTION * +-------------------------------------------------------------------------------------- METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action. CASE iv_action_name. WHEN 'getDomFixValues'. fct_get_dom_fix_values( EXPORTING ir_func_import = io_tech_request_context IMPORTING er_data = er_data ). WHEN OTHERS. RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING message = |EXECUTE_ACTION: Function import { iv_action_name } not implemented|. ENDCASE. ENDMETHOD.
4. Test Function Import im Gateway Client
Jetzt ein kurzer Test im Gateway Client (Transaktion /IWFND/GW_CLIENT), ob das Ganze auch wie gewünscht funktioniert. Die URL ist /sap/opu/odata/sap/ZRL_DOMFIXVALUE_SRV/getDomFixValues?domname=’D_SO_LC’
Voilà! Der Service liefert für die Domäne D_SO_LC die NameValue-Paare zurück.
5. Integration in die Fiori App
Jetzt bauen wir eine SAPUI5, die diesen Service konsumiert. Das gehört inhaltlich eigentlich nicht in einen ABAP Blog. Ich persönlich finde jedoch, dass der Aufruf eines Function Imports in den diversen Forumsbeiträgen und Blogs immer nur partiell beschrieben ist. Deshalb an dieser Stelle einmal eine Schritt für Schritt Anleitung.
5.1 manifest.json
In der manifest.json unter sap.app den OData Service als dataSource registrieren und diese an ein Model binden. Hier wird das Default-Model verwendet.
"sap.app": { "id": "cgi.DomFixValue", "dataSources": { "mainService": { "uri": "/sap/opu/odata/sap/ZRL_DOMFIXVALUE_SRV", "type": "OData", "settings": { "odataVersion": "2.0" } } } } "models": { "": { "dataSource": "mainService", "preload": true, "settings": { "defaultBindingMode": "TwoWay", "defaultOperationMode": "Server" } } }
5.2 neo-app.json
Für die Ausführung in der WebIDE muss folgender Eintrag in der neo-app.json stehen:
{ "path": "/sap/opu/odata", "target": { "type": "destination", "name": "cgigwy", "entryPath": "/sap/opu/odata" }, "description": "cgigwy" }
5.3 Component.js
Das Ausführen des Function Imports ist an die models-Datei ausgelagert.
In der Component.js erfolgt der Aufruf models.createLifecycleStatusModel(this) hinzufügen.
sap.ui.define([ "sap/ui/core/UIComponent", "cgi/DomFixValue/model/models" ], function (UIComponent, models) { "use strict"; return UIComponent.extend("cgi.DomFixValue.Component", { metadata: { manifest: "json" }, /** * The component is initialized by UI5 automatically during the startup of the app and calls the init method once. * @public * @override */ init: function () { // call the base component's init function UIComponent.prototype.init.apply(this, arguments); // enable routing this.getRouter().initialize(); models.createLifecycleStatusModel(this); } }); });
5.4 models.js
In models.js wird dann die Methode createLifecycleStatusModel implementieren. Sie erzeugt ein JSON Model mit Namen lifecycleStatus, mit dessen Hilfe das Ergebnis des Function Imports in der App verwendet werden kann.
sap.ui.define([ "sap/ui/model/json/JSONModel", "sap/ui/Device" ], function (JSONModel, Device) { "use strict"; return { createDeviceModel: function () { var oModel = new JSONModel(Device); oModel.setDefaultBindingMode("OneWay"); return oModel; }, createLifecycleStatusModel: function (oComponent) { var mOptions = { method: "GET", urlParameters: { "domname": "D_SO_LC" }, success: function (oData) { oComponent.setModel(new JSONModel(oData.results), "lifecycleStatus"); }, error: function () { oComponent.setModel(new JSONModel({}), "lifecycleStatus"); } }; oComponent.getModel().callFunction("/getDomFixValues", mOptions); } }; });
Du programmierst, bist ABAP-interessiert und hast Lust coole Projekte mit uns zu machen? Wir suchen dich! Schau doch mal in unserer Stellenbeschreibung vorbei.