OData-Dienst in SAP: Ein umfassender Leitfaden für ABAP-Entwickler

Postman-Benutzeroberfläche für OData-Dienstanruf

Willkommen bei Shock Naue, Ihrem führenden Informationsportal für fundierte Einblicke in die Welt der Technologie. Dieser Artikel bietet ABAP-Entwicklern einen detaillierten Einstieg in das Verständnis und die Implementierung von Odata Service Sap. Wir navigieren Sie durch die Grundlagen, von der Einrichtung Ihrer Testumgebung bis zur Entwicklung und Wartung komplexer OData-Dienste in Ihrem SAP ABAP-Backend.

Einführung in OData in SAP

OData (Open Data Protocol) hat sich als Standard für die Kommunikation mit dem SAP-Backend etabliert, sei es für SAPUI5-Frontends oder andere Integrationsszenarien. Das Ziel dieses Dokuments ist es, ABAP-Entwickler mit dem notwendigen Wissen auszustatten, um OData-Dienste in einem SAP ABAP-basierten Backend-System zu verstehen und zu implementieren. Wir werden die Hintergründe von OData-Diensten beleuchten und zeigen, wie sie getestet werden können.

Um OData zu erklären, werden wir bestehende OData-Dienste aufrufen und diese Aufrufe mit weiteren Optionen erweitern. Als erstes Tool kommt Postman zum Einsatz, dessen Installation der erste Schritt sein wird.

Wichtiger Hinweis: Für dieses Tutorial wird auf Standard-BP-Funktionalitäten zurückgegriffen. Bitte verwenden Sie dieses Tutorial ausschließlich in einer Testumgebung.

Postman für OData-Tests

Installieren Sie Postman (https://www.getpostman.com/downloads/). Postman ist ein leistungsstarkes Werkzeug zum Testen und Ausführen von HTTP(S) REST-Aufrufen. Alternativ können Sie Curl (http://curl.haxx.se/) verwenden, aber in diesem Tutorial werden wir uns auf Postman konzentrieren. Die Beherrschung dieses Tools ist ein wichtiger Schritt, um die Interaktion mit einem odata service sap zu verstehen.

SAP ABAP-Backend

Wir werden einige Demo-Dienste und Demo-Daten von SAP verwenden. Sollten die zugrundeliegenden Tabellen leer sein, können Sie diese über die Transaktion SEPM_DG füllen. Es wird davon ausgegangen, dass Sie den Hostnamen und die Portnummer Ihrer SAP-Installation kennen. Falls nicht, finden Sie diese Informationen in der Transaktion SMICM unter “Springen zu” -> “Dienste”.

Testen Ihrer Umgebung

Starten Sie Postman, erstellen Sie eine Collection, um Ihre Tests und Aufrufe zu speichern, und erstellen Sie Ihren ersten OData-Aufruf, um die Verbindung zu Ihrem Backend zu testen. Wir verwenden einen Standard-SAP-OData-Dienst: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/?$format=xml. In Postman sieht dies wie folgt aus:

Postman-Benutzeroberfläche für OData-DienstanrufPostman-Benutzeroberfläche für OData-Dienstanruf

Wenn Sie diesen Aufruf nun versuchen, erhalten Sie einen Anmeldefehler.

Postman-Fehlermeldung bei OData-AnmeldungPostman-Fehlermeldung bei OData-Anmeldung

Wir müssen unsere Anmeldeinformationen im Tab “Authorization” hinzufügen (Typ: Basic Auth).

Postman-Einstellungen für Basic Auth in OData-AnfragePostman-Einstellungen für Basic Auth in OData-Anfrage

Wenn alles korrekt ist, sehen Sie nach dem Absenden die Entitätstypen im zurückgegebenen Body:

Postman-Antwort mit OData-EntitätstypenPostman-Antwort mit OData-Entitätstypen

Frage: Was müssten Sie tun, um die Antwort im JSON-Format zu erhalten?

OData-Hintergrundwissen

Das Format einer OData-URL ist unten dargestellt.

Diese URL verweist auf ein Service Document, das für OData zwei wesentliche Dinge offenlegt:

  • Die Entitätsmengen (Entity Sets), Funktionen und Singletons, die abgerufen werden können.
  • Ein Metadaten-Dokument (das das Verpackungsformat der Daten anzeigt).

Um die Entitätsmengen anzuzeigen, öffnen Sie den Link in einem neuen Browser-Tab. Beim Scrollen durch die Seite sehen Sie alle aufgelisteten Entitätsmengen (oder Kollektionen): http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/?$format=json.

Das Metadaten-Dokument zeigt die einzelnen Felder, Formate und Navigationseigenschaften aller Kollektionen an. Um die Metadaten für einen beliebigen OData-Dienst anzuzeigen, fügen Sie $metadata am Ende der URL in Ihrem Browser an: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/$metadata.

Um die Daten anzuzeigen, die vom odata service sap bereitgestellt werden, geben Sie einfach die gewünschte Kollektion ein: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/SalesOrderCollection?$format=json.

Wenn Sie diesen URI ausprobieren, werden Sie feststellen, dass es lange dauert, alle Ergebnisse zu erhalten. Meistens möchten Sie nur wenige Elemente aus der Kollektion anzeigen. Um nur eine begrenzte Anzahl von Elementen zu erhalten, können Sie den URI mit Optionen wie $top, $skiptoken, $orderby, $filter erweitern: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/SalesOrderCollection?&$top=10&$skiptoken=5&$filter=BillingStatus%20ne%20'P'&$format=json.

Im obigen URI möchten wir 10 Verkaufsaufträge, die nicht bezahlt sind, wobei die ersten 5 Einträge übersprungen werden. Beachten Sie das “%20”; dies ist eine kodierte Form für ein Leerzeichen. Weitere Informationen finden Sie unter: https://www.w3schools.com/tags/ref_urlencode.asp.

Wir erhalten immer noch viele Daten; wir können wählen, nur eine Untermenge von Feldern zurückzugeben, indem wir die Option $select verwenden: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/SalesOrderCollection?&$top=10&$skiptoken=5&$filter=BillingStatus%20ne%20'P'&$select=SalesOrderID,Status,NetSum,Currency,CustomerName&$format=json.

Wäre es nicht schön, auch die bestellten Produkte in den Positionen zu erhalten? Dafür haben wir die Option $expand: http://services.odata.org/V2/Northwind/Northwind.svc/Products?$format=json&$top=10&$select=ProductNa… (Leider unterstützt der SAP GWDemo OData-Dienst die Option $expand nicht sehr gut, daher ist dies ein anderes Beispiel.)

Glücklicherweise gibt es eine weitere Möglichkeit, von einem Verkaufsauftrag zu den Positionen zu gelangen. Das ist die Definition des Verkaufsauftrags mit seinem Schlüssel (wie hier: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/SalesOrderCollection('1244D0D392BB1EE5B49987627D705A45')) und die Verwendung des anderen Weges zur Erweiterung auf die Positionen über einen Pfad im URI: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/SalesOrderCollection('1244D0D392BB1EE5B49987627D705A45')/salesorderlineitems.

Bitte beachten Sie, dass in diesen letzten beiden URIs GUIDs verwendet werden. Sie werden nicht dieselben GUIDs in Ihrem System haben, daher sollten Sie Ihre URIs ändern, um Ergebnisse zu erhalten.

Frage: Welchen Nutzen könnte die Kombination von $top, $skip und $count haben? Hinweis: Werfen Sie einen Blick auf https://blogs.sap.com/2013/03/20/using-odatas-top-skip-and-count/ und https://blogs.sap.com/2017/12/06/display-countfilterorderbyinlinecounttop-and-skip-operations-using-….

Können Sie einen URI erstellen, bei dem Sie Informationen zu einem Verkaufsauftrag und seinen Positionen abrufen und dabei nur wenige Felder auswählen? Müssen Sie den Schlüssel in die Auswahl aufnehmen, um die Positionen zu erhalten? Warum würden Sie eine Auswahl von Feldern verwenden?

Bislang haben wir nur Informationen abgerufen. Nun möchten wir Änderungen vornehmen. Sie können die Standard-HTTP-Operationen GET, POST, PUT, PATCH, MERGE & DELETE verwenden. Wir werden etwas Einfaches ändern: die ProductDescription eines Produkts. Rufen Sie eine Liste einiger Produkte ab: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/ProductCollection?$top=20.

Wählen Sie ein Produkt aus, das Sie ändern möchten, und rufen Sie die Details ab. Der URI zur Identifizierung ist gegeben, zum Beispiel: http://IhreSystemURL:Portnummer/sap/opu/odata/IWBEP/GWDEMO/ProductCollection('1244D0D392BB1EE5B49984552646FA45'). Verwenden Sie den Body des Ergebnisses als Eingabe für die Aktualisierung.

Suchen Sie nun nach dem Tag <ProductDescription> und ändern Sie die Beschreibung. Stellen Sie sicher, dass Sie den Body als XML eingeben und dies auch in Postman als XML einstellen:

Postman-Anfrage-Body für OData-Update im XML-FormatPostman-Anfrage-Body für OData-Update im XML-Format

Wählen Sie die PATCH-Operation und klicken Sie auf SEND.

Postman-PATCH-Anfrage zur Aktualisierung eines OData-EintragsPostman-PATCH-Anfrage zur Aktualisierung eines OData-Eintrags

Wenn alles gut gegangen ist, haben Sie die Beschreibung dieses Produkts geändert. Überprüfen Sie dies mit einer GET-Operation.

Sollten Sie einen Fehler erhalten, der sich auf ein x-csrf-token bezieht, ändern Sie die GET-Anfrage, indem Sie Folgendes im Header hinzufügen: x-csrf-token=fetch. In der Antwort erhalten Sie ein Token zurück, verwenden Sie diesen Wert in der PATCH-Operation:

Postman-Header für CSRF-Token in OData-AnfragenPostman-Header für CSRF-Token in OData-Anfragen

CSRF (Cross-site Request Forgery) bezeichnet eine Methode des Session-Hijackings, die für böswillige Zwecke genutzt werden kann. Um dies zu verhindern, wird ein CSRF-Token vom SAP-System bereitgestellt, sodass der Browser dieses Token in nachfolgenden Aufrufen auf sichere Weise verwenden kann. Weitere Informationen finden Sie unter: https://en.m.wikipedia.org/wiki/Cross-site_request_forgery und https://stackoverflow.com/questions/5207160/what-is-a-csrf-token-what-is-its-importance-and-how-does….

Frage: Worin besteht der Unterschied zwischen den Operationen PUT und PATCH? Was ist der Ergebnisstatus des PATCH-Aufrufs? Warum? Was sollten Sie in den Body einer DELETE-Operation aufnehmen?

Für weitere Informationen und Übungen zu OData besuchen Sie bitte:
https://blogs.sap.com/2013/10/03/lets-talk-odata-shall-we/
https://sapyard.com/odata-and-sap-netweaver-gateway-part-i-introduction/
https://blogs.sap.com/2016/02/08/odata-everything-that-you-need-to-know-part-1/ und die nachfolgenden Blogbeiträge dieser Serie.
https://www.odata.org/getting-started/basic-tutorial/

Eine sehr gute Referenz zu OData: https://www.odata.org/documentation/odata-version-2-0/uri-conventions/

Erstellung eines einfachen OData-Dienstes in SAP

Einführung

Da unser Fokus auf der Erstellung eines odata service sap liegt, verwenden wir ein recht einfaches Datenmodell: den Geschäftspartner und seine Unterknoten wie Adresse, Telefonnummern usw. Wir werden die Standard-BAPIs und Funktionsbausteine nutzen, um den ABAP-Aufwand gering zu halten.

Die meisten Implementierungen von OData-Diensten in der SAP-Welt verwenden ein separates Gateway-System für die Bereitstellung von OData und ein separates System, in dem die Daten tatsächlich liegen (oftmals ein ECC-System).

Frage: Welchen Vorteil hätte es, zwei verschiedene Systeme zu haben: eines für die Datenspeicherung und das andere für die Bereitstellung von OData, anstatt nur ein System für beide Zwecke zu nutzen?

Definition des OData-Dienstes

In der Transaktion ‘SEGW’ können Sie Ihren OData-Dienst definieren. Beginnen wir mit der Erstellung eines Lese-Dienstes (HTTP “GET”-Operation) für die Geschäftspartner-Entität. Klicken Sie auf “Erstellen” und füllen Sie die angeforderten Parameter aus. Ein leeres OData-Projekt erscheint.

SEGW – Neues OData-Projekt erstellenSEGW – Neues OData-Projekt erstellenInitiales OData-Projekt in SEGW nach ErstellungInitiales OData-Projekt in SEGW nach Erstellung

Was sehen wir im Baum?
Zuerst den Namen des OData-Dienstes. In diesem Fall “Z_JW_BUSPARTNER”. Darunter finden wir den Knoten “Data Model”. In den Unterknoten des “Data Model”-Knotens werden die Daten-Definition und die Beziehungen zwischen ihnen definiert. Alle Funktionen werden hier ebenfalls angezeigt. Der nächste Knoten ist “Service Implementation”. Hier werden die möglichen Operationen für die Entitäten im “Data Model” definiert. Im Bereich “Runtime Artefacts” werden die (generierten) Klassen zusammengefasst. Unter “Service Maintenance” werden die Details der Registrierung des Dienstes auf dem Gateway-System angezeigt.

Um die Felder für den Geschäftspartner zu definieren, importieren wir die Struktur BUT000, verwenden aber nur einige Felder. Klicken Sie mit der rechten Maustaste auf den Knoten “Data Model” und wählen Sie “Import -> DDIC structure”.

OData-Dienst – DDIC-Struktur importierenOData-Dienst – DDIC-Struktur importieren

Füllen Sie die Felder aus und wählen Sie diejenigen aus, die Sie verwenden möchten. Da ich meinen Dienst nur für Organisationen verwenden werde, wähle ich zunächst nur die Felder “Partner”, “NAME_ORG1”, “NAME_ORG”, “BU_SORT1” & “BU_SORT2”. Das Feld “Partner” wird als Schlüssel markiert.

Feldauswahl für OData-Entität aus BUT000Feldauswahl für OData-Entität aus BUT000

Frage: Warum müssen wir mindestens einen Eintrag als Schlüssel markieren?

Jetzt müssen wir festlegen, was wir mit den Feldern tun können. Da wir alle Felder für CRUD (Create, Read, Update, Delete) verfügbar machen möchten, markieren wir sie alle für diese Operationen. Beachten Sie jedoch, dass wir nicht alle Felder markieren.

Frage: Welche Felder sind nicht markiert und warum?

Nach der Generierung ist der erste Teil des OData-Dienstes erstellt! Es ist Best Practice, die vorgeschlagenen Namen so zu belassen, wie sie sind, aber Sie können die Namen der Klassen ändern. Später werden wir die Klassen mit “_DPC_EXT” und “_MPC_EXT” für die Implementierung unserer eigenen Logik verwenden.

Generierte OData-Dienstklassen in SEGWGenerierte OData-Dienstklassen in SEGW

Nach der Generierung sollten Sie den Dienst in SICF registrieren. Wählen Sie den Eintrag unter dem Knoten “Service Maintenance” aus. Drücken Sie einfach die Schaltfläche “Register”.

Bestätigung der OData-DienstregistrierungBestätigung der OData-Dienstregistrierung

Und wir können es sofort testen!

Testen von OData-Diensten in der SAP GUI

Das Testen eines odata service sap ist recht einfach. SAP hat eine separate Transaktion zum Testen von OData-Diensten erstellt, die Sie über die Schaltfläche mit dem Schraubenschlüssel erreichen:

Sie gelangen zum folgenden Bildschirm. Der Basis-URI sollte vorausgefüllt sein.

SAP GUI – Testbildschirm für OData-DiensteSAP GUI – Testbildschirm für OData-Dienste

Über die Schaltflächen “Entity Sets” und/oder “Add URI Option” können Sie den URI manipulieren.

Frage: Versuchen Sie, die Metadaten für Ihren Dienst sowie die Einträge für die Geschäftspartner abzurufen. Welchen Rückgabestatus hat der Aufruf für die Einträge, die die Geschäftspartner abrufen?

Bitte beachten Sie, dass in dieser SAP-Transaktion nur der letzte Teil des URI angezeigt wird, beginnend mit der Dienst-Root.

Implementierung des Codes für den OData-Dienst zum Abrufen einer Liste von Entitäten

Sie werden bemerkt haben, dass der Dienst noch keine Ergebnisse liefert, sondern einen “501”-Fehler (not implemented). Und genau das werden wir jetzt tun. Bei der Generierung des Dienstes fragte das System nach Namen für Klassen. Wir werden die dort definierte Data Provider-Klasse verwenden. Standardmäßig ist dies die Klasse, die mit “_DPC_EXT” endet; den Namen der Klasse finden Sie auch unter dem Knoten “Service Implementation”. Es gibt fünf geerbte Methoden, die mit der Geschäftspartner-Entität zusammenhängen.

Methoden der Data Provider-Klasse für Geschäftspartner-EntitätMethoden der Data Provider-Klasse für Geschäftspartner-Entität

Die ersten zu veröffentlichenden Operationen sind die Lese-Operationen, und daher werden die Methoden “BUSINESSPARTNERS_GET_ENTITY” und “BUSINESSPARTNERS_GET_ENTITYSET” neu implementiert.

Frage: Worin besteht der Unterschied zwischen diesen beiden Methoden?

Da wir das Data Dictionary-Element “BUT000” als Quelle für unsere Entität verwendet haben, können wir Einträge direkt aus dieser Tabelle in die Entität selektieren. In den meisten Fällen werden Sie eine Feldliste und einen Join in Ihrer Selektion verwenden oder einen BAPI- oder Funktionsbaustein-Aufruf.

Warnung: Diese Lösung könnte in Systemen mit vielen Geschäftspartnern zu Performance-Problemen führen.

Implementierung für das Entity Set:

METHOD businesspartners_get_entityset. "Redefinition
  SELECT * FROM but000 INTO TABLE et_entityset.
ENDMETHOD. 

Mit dieser einzigen Codezeile haben Sie Ihren OData-Dienst für das Abrufen aller Geschäftspartner am Laufen!

Betrachten Sie nun die Methode, die Sie gerade neu implementiert haben, genauer. Wie Sie sehen, gibt es viele Parameter in dieser Methode. Werfen Sie einen Blick darauf im Debugger (setzen Sie einen externen Breakpoint); einige sprechen für sich. Am wichtigsten ist der Exportparameter “ET_ENTITYSET”. In diesem Parameter geben Sie Ihre Ergebnisse zurück, die letztendlich das Ergebnis-Set des OData-Dienstes sein werden. Der Parameter IS_PAGING enthält die Optionen $top & $skip, die Parameter IT_FILTER_SELECT_OPTIONS, IT_KEY_TAB, IT_NAVIGATION_PATH, IT_ORDER, IV_FILTER_STRING und IV_SEARCH_STRING sind für andere Optionen im OData-URI. Einige davon werden durch Standardklassen in SAP implementiert. Weitere Informationen finden Sie in diesem Blog: https://blogs.sap.com/2017/12/06/display-countfilterorderbyinlinecounttop-and-skip-operations-using-….

Die Implementierung dieser Standardfunktionalitäten führt zu der folgenden Methode:

METHOD businesspartners_get_entityset. "Redefinition
  SELECT * FROM but000 INTO TABLE et_entityset.

  *** $inlinecount query option for all count entries.
  IF io_tech_request_context->has_inlinecount( ) = abap_true.
    DESCRIBE TABLE et_entityset LINES es_response_context-inlinecount.
  ELSE.
    CLEAR es_response_context-inlinecount.
  ENDIF.

  *** The module for Filter conditions
  CALL METHOD /iwbep/cl_mgw_data_util=>filtering
    EXPORTING
      it_select_options = it_filter_select_options
    CHANGING
      ct_data           = et_entityset.

  *** The module for $top and $skip Query Options
  CALL METHOD /iwbep/cl_mgw_data_util=>paging
    EXPORTING
      is_paging = is_paging
    CHANGING
      ct_data   = et_entityset.

  *** The module for Orderby condition
  CALL METHOD /iwbep/cl_mgw_data_util=>orderby
    EXPORTING
      it_order = it_order
    CHANGING
      ct_data  = et_entityset.
ENDMETHOD. 

Wäre es nicht schön, eine Meldung anzubieten, wenn keine Ergebnisse gefunden wurden? Lassen Sie uns das implementieren. In den Methoden zur Rückgabe von Entitäten sind zwei Ausnahmen definiert: eine vom Typ “/IWBEP/CX_MGW_BUSI_EXCEPTION” und eine vom Typ “/IWBEP/CX_MGW_TECH_EXCEPTION”. Die erste ist für Probleme mit Entitäten, wie Berechtigungen oder keine gültigen Einträge gefunden, die zweite für technische Probleme, wie unerwartete Eingaben, Operatoren oder ähnliches. Eine solche Meldung wurde angezeigt, nachdem der Dienst gerade generiert, aber noch keine Methoden implementiert wurden. Diese Ausnahme führt zu einer HTTP-Fehlermeldung (z. B. ein 501-Ergebnis).

Des Weiteren können wir einen Message Container verwenden, um mehrere Nachrichten zu speichern. Siehe https://help.sap.com/doc/saphelp_gateway20sp12/2.0/en-US/25/21aecce9db435daaea433071ff7d94/content.h….

Die Implementierung dieses Dienstes wird durch das Hinzufügen einer Prüfung der Auswahl abgeschlossen, um festzustellen, ob etwas gefunden wurde:

 IF sy-subrc NE 0. "No BP's found.
   DATA(lo_message_container) = me->mo_context->get_message_container( ).
   lo_message_container->add_message( iv_msg_type = /iwbep/cl_cos_logger=>warning
                                     iv_msg_id = 'SA' "SA(419) = No objects found
                                     iv_msg_number = 419
                                     iv_add_to_response_header = abap_true ).
 ENDIF. 

Der Message Container ist vielseitiger als nur diese Methode. Erkunden und probieren Sie Dinge aus. Die Verwaltung von Nachrichten ist ein grundlegender Aspekt für jeden sap pco oder OData-Dienst, der robuste Fehlerbehandlung erfordert.

Fühlen Sie sich frei, diesen Dienst zu testen.

Implementierung des Lese-Dienstes für eine einzelne Entität

Mit der Erfahrung bei der Implementierung des Dienstes zum Abrufen eines Arrays von Ergebnissen für das Ergebnis-Set ist es einfach, den Dienst zum Abrufen eines einzelnen Eintrags zu implementieren. Die hier zu redefinierende Methode ist die namens “BUSINESSPARTNERS_GET_ENTITY”. Der Dienst erwartet einen gültigen Schlüssel für die Entität; in diesem Fall ist der Schlüssel eine Geschäftspartnernummer. Dies wird in den Parameter IT_KEY_TAB an die Methode übergeben. Eine einfache Lösung könnte der folgende Code sein:

DATA(lv_bu_partner_raw) = CONV bu_partner( |{ it_key_tab[ name = 'Partner' ]-value }| ).
DATA(lv_bu_partner) = CONV bu_partner( |{ lv_bu_partner_raw ALPHA = IN }| ).
SELECT SINGLE * FROM but000 INTO CORRESPONDING FIELDS OF er_entity WHERE partner = lv_bu_partner. 

Frage: Welche Fehlerbehandlung würden Sie implementieren? Wie würden Sie die Nachrichten an den Aufrufer des OData-Dienstes übermitteln?

Implementierung des Update / Create / Delete Dienstes

Informationen abzurufen ist eine Sache, aber wir möchten wirklich Dinge mit unseren Entitäten tun. Ich werde den Update-Dienst erklären und es Ihnen überlassen, die Create- und Delete-Dienste als Übung zu implementieren. Sie werden mittlerweile erraten können, welche Methoden neu definiert werden müssen.

Die Daten, die im System aktualisiert werden sollen, werden über den Parameter io_data_provider übertragen. Sie können die Daten abrufen, indem Sie die Methode read_entry_data() aufrufen. Die Aktualisierung erfolgt über die HTTP-“PUT”-Methode. Der Schlüssel der Eingabe wird auch im Parameter IT_KEY_TAB angegeben; es ist eine gute Praxis, den Wert aus dem io_data_provider mit dem Wert im Parameter IT_KEY_TAB zu vergleichen.

Es ist auch schön, den aktualisierten Wert über den Parameter ER_ENTITY an den Benutzer zurückzugeben.

Der vereinfachte Code könnte so aussehen:

 io_data_provider->read_entry_data( IMPORTING es_data = ls_entity ).
 READ TABLE it_key_tab INTO DATA(ls_key_tab) INDEX 1.
 * make sure the value matches with the OData payload
 IF ls_key_tab-value EQ ls_entity-partner.
   CALL FUNCTION 'BAPI_BUPA_CENTRAL_CHANGE'
     EXPORTING
       businesspartner = ls_entity-partner
     TABLES
       return          = lt_return.
 ELSE.
   * raise message: entity not found
 ENDIF.
 er_entity = ls_entity. 

Tipp zum einfachen Testen: Sie möchten eine vorhandene Entität aktualisieren; führen Sie also zuerst einen GET-Aufruf für eine einzelne Entität aus. Kopieren Sie das Ergebnis der Antwort und verwenden Sie es als Ausgangspunkt für Ihren HTTP-Anfrage-Body. In der SAP GUI gibt es sogar eine schöne Schaltfläche dafür. Und vergessen Sie nicht, entweder führende Nullen in Ihrem Code hinzuzufügen, wenn Sie nachsichtig sein möchten, oder den korrekten Schlüssel mit führenden Nullen zu übergeben, sobald Sie ein Update aufrufen. Eine korrekte Handhabung von Schlüsseln und Berechtigungen ist auch entscheidend für die Sicherheit, ähnlich wie bei der Verwaltung von Rollen über sap su24.

Frage: Welchen Statuscode erhalten Sie, wenn Sie ein erfolgreiches Update durchgeführt haben? Warum erhalten wir diesen bestimmten Statuscode?

Fahren Sie nun mit der Implementierung der Erstellungs- und Löschdienste fort und testen Sie diese. Für die Erstellung von Geschäftspartnern könnten Sie “BAPI_BUPA_CREATE_FROM_DATA” verwenden. Verwenden Sie die Kategorie ‘1’ für Personen und ‘2’ für Organisationen.

Zum Löschen können Sie entweder nur das Archivierungskennzeichen setzen, oder Sie könnten den Code der SAP-Reports BUPA_PREPARE_DA (Transaktion BUPA_PRE_DA) und BUPA_TEST_DELETE (Transaktion BUPA_DEL) wiederverwenden. Die Nutzung von OData in modernen Kontexten, wie etwa abap cloud, erfordert ebenfalls ein tiefes Verständnis dieser CRUD-Operationen.

Frage: Ist es notwendig, einen Body mit Details für die HTTP-Anfrage für die Löschoperation bereitzustellen?

Frage: Wie erfahren Sie den Schlüssel der Entität, die mit einer HTTP-POST-Operation erstellt wurde?

Hinzufügen von Assoziationen zu Ihrem OData-Dienst

Nachdem unser einfacher OData-Dienst läuft, ist es Zeit, ihn zu erweitern. Wir fügen die Möglichkeit hinzu, Adressen hinzuzufügen. Der Einfachheit halber werde ich in diesem Beispiel nur Telefonnummern verwalten. Für die Implementierung habe ich die Funktionsbausteine BAPI_BUPA_ADDRESSES_GET, BAPI_BUPA_ADDRESS_GETDETAIL, BAPI_BUPA_ADDRESS_ADD, BAPI_BUPA_ADDRESS_CHANGE und BAPI_BUPA_ADDRESS_REMOVE verwendet. Die Integration von Datenströmen, wie sie ein sap kafka-Setup bietet, kann die Notwendigkeit robuster OData-Dienste für die Datenbereitstellung weiter erhöhen.

Im OData-Dienst wird eine zweite Entität für die Telefonnummern (Telephone & TelephoneSet) erstellt. In diesem Beispiel werden nur die minimalen Felder gepflegt:

OData-Dienst – Felder der Telefonnummern-EntitätOData-Dienst – Felder der Telefonnummern-Entität

Nun ist es Zeit, die Assoziation zwischen Partner und Telefonnummern hinzuzufügen.

Öffnen Sie den Knoten “Data Model” des OData-Dienstes und wählen Sie “Create” im Knoten “Associations”.

OData-Dienst – Assoziation erstellenOData-Dienst – Assoziation erstellen

Die Assoziation führt vom Geschäftspartner zum Telefon, daher nennen wir sie BusinessPartnerGetTelephones. Jeder Geschäftspartner kann null bis viele Telefonnummern haben, und dies wird in der Kardinalität verwendet. Generieren Sie bei Bedarf auch die Navigationseigenschaften. Navigation Property: Eine Eigenschaft eines Eintrags, die eine Verknüpfung von diesem Eintrag zu einem oder mehreren verwandten Einträgen darstellt. Eine Navigation Property ist kein struktureller Bestandteil des Eintrags, zu dem sie gehört. Eine effiziente Nutzung von OData-Diensten kann auch durch die Anwendung von sap fes für verbesserte Frontend-Leistung unterstützt werden.

OData-Dienst – Assoziation: Kardinalität und NavigationseigenschaftenOData-Dienst – Assoziation: Kardinalität und Navigationseigenschaften

Geben Sie die “referential constraints” (die Felder, die zum Verknüpfen der beiden Entitäten verwendet werden) ein.

Und bestätigen Sie die Übersicht:

OData-Dienst – Übersicht der AssoziationserstellungOData-Dienst – Übersicht der Assoziationserstellung

Und die Assoziation ist erstellt, einschließlich der Navigationseigenschaften.

Erstellte Assoziation und Navigationseigenschaften im OData-ModellErstellte Assoziation und Navigationseigenschaften im OData-Modell

Frage: Wie würde der URI aussehen, um die Assoziation zu testen?

Worin besteht der Unterschied zwischen einem URI mit $expand und der Verwendung eines URI mit einem Association/Navigation Path? (Hinweis: siehe diesen Artikel)

Was wäre das Ergebnis, wenn Sie den URI in den beiden vorherigen Fragen getestet hätten? Warum?

Nachdem die Dienste definiert sind, muss die Implementierung noch kodiert werden. Sobald dies abgeschlossen ist, testen Sie Ihre Lösung, indem Sie einen Geschäftspartner erstellen, Telefonnummern hinzufügen, ändern und löschen. Es wäre sinnvoll, die Navigation sowohl über eine Navigation Property als auch über eine $expand-Option zu testen. Zum Beispiel: /BUSPARTNER_SRV/BusinessPartnerSet('14')/TelephoneSet und /BUSPARTNER_SRV/BusinessPartnerSet('14')/?$expand=TelephoneSet.

Fazit

Sie haben nun einen grundlegenden OData-Dienst erstellt und Einblicke in die Theorie hinter OData gewonnen. Wir hoffen, dieses Tutorial hat Ihnen gefallen und Sie ermutigt, Ihr Wissen über odata service sap weiter zu vertiefen. Die Fähigkeit, robuste und effiziente OData-Dienste zu entwickeln, ist für jeden ABAP-Entwickler, der mit modernen SAP-Architekturen arbeitet, unerlässlich.

Wenn Sie weitere Fragen haben oder tiefer in spezifische OData-Funktionalitäten eintauchen möchten, laden wir Sie ein, die verlinkten Ressourcen zu erkunden und unsere zukünftigen Artikel auf Shock Naue zu verfolgen. Beginnen Sie noch heute mit der Entwicklung Ihrer eigenen OData-Dienste und optimieren Sie die Kommunikation in Ihren SAP-Systemen!

Referenzen