Florian Tent
 - 12. September 2019

ODATA Grundlagen: Services anlegen und testen

Wissensmanagement

In diesem Blogbeitrag möchte ich Ihnen zeigen, wie Sie einen ODATA-Service anlegen und testen können. Dabei erkläre ich zuerst einmal das ODATA Model mit Entitätstypen und EDM-Typen. Danach zeige ich Ihnen, wie Sie alle 5 Standard-Methoden des ODATA-Services implementieren und testen können.

Ich zeige Ihnen hierbei mein Best-Practice-Vorgehen zum Arbeiten mit ODATA und weise gelegentlich auf weitere Alternativen hin.

ODATA Model

Das ODATA Model bildet das Datenmodell eines ODATA-Services ab. Der ein oder andere kennt den Begriff „Entität“ sicherlich noch aus alten Datenbank-Vorlesungen. Falls nicht – auch nicht schlimm, denn das Ganze ist schnell erklärt: Einen Entitätstypen können Sie sich wie eine ABAP-Struktur vorstellen. Sie definieren Felder mit den entsprechenden Datentypen und einigen weiteren Eigenschaften. Allerdings haben Sie hierfür nicht die ABAP-Datentypen zur Verfügung.

ODATA ist eine Schnittstellentechnologie, welche nicht nur von SAP verwendet wird. Daher gelten hier die EDM-Datentypen. In den meisten Fällen gibt es im entsprechenden SAP-Backend auch eine Struktur mit genau denselben Feldern und SAP Datentypen, die dem Entitätstypen gleicht. Aber genug der Theorie, nun zeige ich Ihnen, wie Sie Ihre ersten Entitätstypen anlegen können.

Entitätstyp anlegen

Es gibt verschiedene Möglichkeiten, einen Entitätstypen anzulegen. Sie können die Felder beispielsweise manuell einpflegen und mappen oder direkt aus einer entsprechenden SAP-Struktur importieren. Ich erspare mir gerne die Arbeit und importiere die Felder. Dafür muss ich mir also zunächst eine entsprechende ABAP Struktur in der Transaktion SE11 anlegen:

Für mein Beispiel will ich eine Fiori-Anwendung schreiben, welche mit Personen arbeitet. Dafür habe ich mir eine Struktur angelegt, welche eine Personalnummer, verschiedene Namensfelder und das Geburtsdatum enthält. Auf Basis dieser Struktur will ich jetzt einen Entitätstypen anlegen. Dafür gehe ich in die Transaktion SEGW und lege mir erst einmal ein ODATA-Projekt an.

ODATA Projekt anlegen

Sie sollten nun ein neues ODATA-Projekt mit 4 automatisch generierten Unterordnern vor sich haben. Mit Rechtsklick auf „Data Model“ bekommen Sie nun die Optionen, einen neuen Entitätstypen frei anzulegen oder aus einer ABAP-Dictionary-Struktur zu importieren:

Zuerst geben Sie den Namen Ihres Entitätstypen an und die eben angelegte Dictionary-Struktur, aus der Sie die Felder importieren möchten:

Entitätstyp anlegen Assistent 1

Im Anschluss legen Sie fest, welche Felder aus der Struktur mit in den ODATA-Service übernommen werden sollen:

Entitätstyp anlegen Assistent 2

Als letztes legen Sie den Schlüssel für die Entität fest. Dieser Schritt wird später großen Einfluss haben. Wichtig ist, dass später jedes Entity eindeutig über den Schlüssel identifiziert werden kann. Ich versuche immer, dafür mit so wenigen Feldern wie möglich auszukommen, um es mir später nicht unnötig kompliziert zu machen. In diesem Falle reicht mir die Personalnummer aus, um jede Person eindeutig zu identifizieren:

Entitätstyp anlegen Assistent 3

Ihren ersten Entitätstypen haben Sie hiermit bereits angelegt. Er sollte nun im Ordner „Data Model“ unter „Entitätstypen“ sichtbar sein. Unter Ihrem Entitätstypen sehen Sie nun Eigenschaften und Navigationseigenschaften. Für diesen Fall sind erst einmal die Eigenschaften interessant: Mit einem Doppelklick können Sie sich ansehen, welche Felder mit welchen EDM-Typen Sie im Entitätstypen haben, welche Eigenschaften dazu gehören und zu welchem Feld Ihrer Struktur diese gemapped sind. Das Mapping von ABAP-Datentyp zu EDM-Typ wurde beim Erstellen automatisch vorgenommen.

Entitätstyp Eigenschaften

EDM-Typen

Wie Sie sehen können, weichen die EDM-Typen etwas von den ABAP-Typen ab. Mit F4 (Suchhilfe) auf eines der EDM-Coretyp Felder können Sie sich alle vorhandenen EDM-Typen anzeigen lassen:

Übersicht EDM-Typen

In sehr vielen Fällen wird der ABAP-Datentyp auf den Edm.String-Typen abgebildet. Häufig passt das auch gut für die Datenübertragung. Allerdings habe ich festgestellt, dass zum Beispiel der ABAP Boolean als Char1 auch als String und nicht als Edm.Boolean abgebildet wird. Das korrigiere ich immer nachträglich. Ansonsten benötigen Sie ein zusätzliches Mapping sowohl im Frontend als auch im Backend, um mit dem Feld weiterarbeiten zu können.

Auch bei der Übertragung von Daten sollten Sie aufpassen: ODATA hat keinen Datentyp für ein normales Datum. Es gibt nur den Typen Edm.DateTime, welcher neben dem Datum auch noch die Uhrzeit und die Zeitzone überträgt. Übertragen Sie ein normales Datum aus dem Backend, werden die fehlenden Informationen einfach standardmäßig aufgefüllt. Im Frontend müssen Sie das Datum dann wieder in das gewünschte Format bringen und die zusätzlichen Informationen wieder rausfiltern. Bei der Übertragung vom Frontend ans Backend kann es aufgrund der Zeitzonen zu einer Verschiebung des Datums um einen Tag kommen. Das sollte dann im besten Fall direkt im Frontend vor der Datenübertragung schon korrigiert werden. Bei Daten ist es auch wichtig, den Haken bei der Eigenschaft „Nullwerte möglich“ zu setzen. Ansonsten müssen Sie zwangsläufig immer einen Wert mitliefern.

Nachdem alle Eigenschaften korrigiert sind, klicken Sie oben auf den Button „Laufzeitobjekte generieren“. Dieser prüft das Projekt auf Konsistenz und erzeugt die für die Datenübertragung benötigten Klassen mit den entsprechenden Schnittstellen:

Laufzeitobjekte erzeugen

Service registrieren

Ihr Service ist im Backend nun angelegt, kann aber von außen noch nicht gesehen werden. Um dies zu ermöglichen, müssen Sie ihn noch registrieren. Hierfür gibt es wieder verschiedene Möglichkeiten. Normalerweise wird der Service entweder in der SAP Cloud Plattform (SCP) oder auf einem Gateway-System registriert. Die Services direkt auf dem Backend-SAP-System zu registrieren, funktioniert auch, wird meist aber aus Sicherheitsgründen nur zu Testzwecken genutzt. Ich werde die Services im Folgenden auf einem extra Gateway-System registrieren.

Ich melde mich dazu entsprechend am Gateway-System an und starte die Transaktion /n/IWFND/MAINT_SERVICE . Dort füge ich den Service über die entsprechende Schaltfläche hinzu:

ODATA Service hinzufügen

Im ersten Schritt wähle ich nun das Backend-System aus, auf dem ich meinen ODATA-Service implementiert habe:

System auswählen

Sollte Ihr System nicht in der Suchhilfe zu finden sein, sind noch Konfigurationen am System notwendig. Darauf werde ich in diesem Tutorial nicht näher eingehen. Nachdem Sie Ihr System ausgewählt haben, suchen Sie in der Liste euren Service und fügen diesen dann hinzu. Im folgenden Fenster spezifizieren Sie noch das Entwicklungspaket. Schon ist der Service erfolgreich registriert:

Service hinzufügen

ODATA Services

Sie haben jetzt Ihren Entitätstypen angelegt und die Eigenschaften der Felder entsprechend Ihrer Wünsche angepasst. Nun wird es Zeit, die Datenübertragung zu ermöglichen. Dafür gibt es die bereits erwähnten 5 Standard-Methoden. Im Folgenden werde ich alle 5 Methoden kurz besprechen und für unser Beispiel kurz implementieren. Dafür doppelklicken Sie auf den Ordner „Laufzeitartefakte“ im ODATA-Projekt (auf dem Backend-System) und öffnen die ABAP-Klasse, welche auf „DPC_EXT“ endet. Ganz wichtig ist hierbei, dass Sie diese Klasse nehmen. In der Klasse, welche auf „DPC“ endet, finden Sie dieselben Methoden. Ihre Änderungen werden hier aber jedes Mal komplett überschrieben, wenn Sie die Laufzeitobjekte nach einer Änderung am Datenmodell neu generieren. Die „DPC_EXT“-Klasse ist eine Erweiterung der „DPC“-Klasse. Daher haben Sie hier die Möglichkeit, alle geerbten Methoden zu redefinieren.

DPC_EXT Klasse

Die 5 Service-Implementierungen werden aus der Klasse …_DPC geerbt und werden entsprechend in der Methoden-Übersicht der Klasse aufgeführt:

Service-Implementierungen

GET_ENTITYSET

GET_ENTITYSET liefert eine Menge von Entitäten zurück. Dies wird zum Beispiel häufig verwendet, um eine Liste von Elementen zu befüllen. In unserem Fall der SplitApp verwenden Sie den Service dafür, die Masterliste auf der linken Seite des Bildschirms zu befüllen. Hierfür rufen Sie den Service aus dem Frontend ohne Filter auf und steuern im Backend, welcher Benutzer welche Personen sehen soll.

Nachdem Sie in den Änderungsmodus gewechselt sind, können Sie die Methode GET_ENTITYSET für Ihren Entitätstypen redefinieren. Dadurch legen Sie in der Klasse DPC_EXT eine eigene Implementierung zu der geerbten Methode an:

Service-Implementierung redefinieren

Innerhalb dieser Methode können Sie nun die vom Frontend übergebenen Filter auslesen, die Anfragen im Backend verarbeiten und die Ergebnisse wieder in die Schnittstelle füllen. Da in diesem Fall kein Filter benötigt wird, sparen Sie sich das an dieser Stelle. Aber keine Sorge, auf die Filter werde ich in den nächsten Services noch eingehen. Für die Methode GET_ENTITYSET steht die Tabelle et_entityset als Container für die Ergebnisdaten zur Verfügung. Diese müssen Sie also in dieser Methode befüllen.

Ich habe mir eine eigene Klasse für den Entitätstypen angelegt, welche ich zum Befüllen der Schnittstelle verwenden werde. Theoretisch können Sie den Quellcode natürlich einfach in die Methode GET_ENTITYSET implementieren, aus meiner Sicht ist eine Trennung an dieser Stelle allerdings sauberer. Die Tabelle et_entityset basiert auf dem Entitätstypen, welcher wiederum auf unserer ursprünglich angelegten Struktur basiert. Sie können also einfach einen Tabellentyp dieser Struktur als Rückgabe für diese Methode wählen und das et_entityset somit direkt befüllen. Sollten Sie nicht alle Felder aus der Struktur übernommen haben oder weitere Felder zum Entitätstypen hinzugefügt haben, wäre an dieser Stelle noch ein Mapping notwendig.

GET_ENTITYSET

Ihre erste Service-Implementierung ist nun fertig gestellt. Aber funktioniert das auch alles so, wie Sie sich das vorstellen? Sie wollen Ihren neuen Service natürlich direkt testen, bevor Sie das Frontend dazu fertig gestellt haben. Hierfür loggen Sie sich wieder im Gateway System ein und starten die Transaktion /n/iwfnd/maint_service. Hier haben Sie die Möglichkeit, den Service über den SAP Gateway Client zu testen:

SAP Gateway Client

Hier ist automatisch die HTTP-Methode „GET“ und die zu unserem ODATA-Service passende Request-URI voreingestellt. Den ersten Test starten Sie, indem Sie die hinterlegten Einstellungen ausführen. Hat bis hierhin alles gut funktioniert, sollten Sie den Status Code 200 OK in einem grün hinterlegten Fenster sehen. Zusätzlich steht im Fenster rechts unten die Antwort, welche alle von uns hinterlegten Entitätstypen enthält:

Service Metadate

Sollte das bei Ihnen nicht funktioniert haben, probieren Sie die Transaktion /n/iwfnd/error_log aus. Hier finden Sie meist hilfreiche Debugging-Informationen, wenn ODATA-Aufrufe fehlgeschlagen sind.

Um den gerade implementierten Service GET_ENTITYSET zu testen, müssen Sie lediglich die URL hinter dem _SRV abändern. Hier tragen Sie einfach das Set des eben von Ihnen erstellten Entitätstypen ein: PersonSet

Hier bekommen Sie nun für jede Person, die Ihre Methode GET_ENTITYSET zurückliefert, einen Eintrag:

Test GET_ENTITYSET

Falls Sie hierbei nicht den Code 200, sondern einen Fehler bekommen, empfehle ich 2 Möglichkeiten zum Debugging: Sie können direkt am Anfang der Methode GET_ENTITYSET einen externen Breakpoint setzen. Sollten Sie erst gar nicht bis dahin kommen, hilft wieder die Transaktion /n/iwfnd/error_log auf dem Gateway System. Sobald bei Ihnen auch der grüne Statuscode und die richtigen Personen im Ergebnis stehen, haben Sie es geschafft! Ihr GET_ENTITYSET funktioniert!

GET_ENTITY

GET_ENTITY liefert als Ergebnis ein einziges, spezielles Entity anstelle einer Ergebnismenge. Bei diesem Service muss der eindeutige Schlüssel mitgegeben werden, um das Entity zu identifizieren. Um den Service zu implementieren, redefinieren Sie die Methode GET_ENTITY aus Ihrer DPC_EXT Klasse analog zum vorigen Vorgehen.

Innerhalb der Methode müssen Sie zuerst die mitgegebene ID auslesen. Die regulär übergebene ID ist in der Tabelle IT_KEYTAB als Key-Value-Pair zu finden. Der Schlüssel ist hierbei die Bezeichnung des jeweiligen Attributs – in diesem Fall „Pernr“, da Sie dies als Schlüssel Ihres Entitätstypen definiert haben. Der entsprechende Wert dazu steht dann im „Value“ Attribut des Tabelleneintrages. Ich lese die PerNr in diesem Fall wie folgt aus:

GET_ENTITYSET

Die Ergebnismenge aus dem Backend wird am Ende in den Export-Parameter er_entity geschrieben. Hierbei handelt es sich um eine Struktur vom Typ des ODATA-Entitätstypen. Für die Backend-Logik liegt es an Ihnen, den passenden Personensatz zur übergebenen Personalnummer aufzubereiten.

Zum Testen der Implementierung gehe ich wieder in den SAP Gateway Client auf meinem Gateway-System und passe die URL etwas an, sodass ich die entsprechende URL zu meinem Personenset übergebe: /sap/opu/odata/sap/ZFTENT_HOWTO_ODATA_SRV/PersonSet(‚12345678‘). Wenn alles fehlerfrei ist, bekomme ich den grünen Code 200 zurück und in dem XML-Dokument die Details zu meiner Person:

Ergebnis GET_ENTITY

CREATE_ENTITY

Create Entity soll einen neuen Datensatz im Backend anlegen. Dafür müssen vom Frontend natürlich alle relevanten Eigenschaften mitgegeben werden. Um den Service zu implementieren, redefinieren Sie die Methode CREATE_ENTITY der DPC_EXT Klasse analog zu den vorigen Malen. In der Methode suchen Sie diesmal nicht nach einem Key, sondern nach allen relevanten Informationen, um den neuen Datensatz anzulegen. Dafür wird Ihnen das Objekt io_data_provider mitgeliefert. Mit der Methode read_entry_data() bekommen Sie alle vom Frontend übergebenen Daten zurück.

Für den Export-Parameter er_entity müssen Sie eine Struktur vom Typ des ODATA-Entitätstypen mitgeben. Die ausgelesenen Daten können Sie nun im Backend verwenden, um einen entsprechenden Datensatz zu erstellen. Wichtig hierbei ist, dass Sie den Export-Parameter er_entity vor Ende der Methode befüllen, da ansonsten der HTTP-Fehlercode 500 zurückgegeben wird. Normalerweise werden einige Eigenschaften im Backend generiert und können nach Erstellung dann an das Frontend zurückgegeben werden. Da dies bei mir nicht der Fall ist, übergebe ich einfach die selben Daten wieder zurück:

CREATE_ENTITY

Zum Testen müssen Sie dementsprechend Informationen für den zu erstellenden Backend-Datensatz mitgeben. Im Gateway-Client können Sie sich dafür einfach behelfen: Verwenden Sie erst den vorhin beschriebenen GET_ENTITY Aufruf, um einen Datensatz im rechten XML-Ergebnisfeld zu haben. Dann können Sie einfach rechts oben in der Leiste auf „Als Anf. verwenden“ klicken, um die XML-Struktur im linken Feld zu sehen:

Resp. als Anf. verwenden

In der XML-Struktur auf der linken Seite löschen Sie nun alles zwischen dem <entry>- und dem <content>-Tag. Jetzt sollte der verbleibende Teil etwa so aussehen:

Anzupassender xml Datensatz

Den verbliebenen Datensatz können Sie anpassen, sodass er Ihrem neu einzufügendem Satz entspricht. Nun müssen Sie nur noch die HTTP auf „Post“ stellen und dieselbe URL wie schon für den Test vom GET_ENTITYSET verwenden: /sap/opu/odata/sap/ZFTENT_HOWTO_ODATA_SRV/PersonSet

Wenn alles funktioniert hab, sollten Sie jetzt den grünen HTTP-Statuscode 201 – Created sehen und den zurückgelieferten Datensatz im Ergebnis auf der rechten Seite:

Entity angelegt 201

UPDATE_ENTITY

Für die UPDATE_ENTITY-Methode übergeben Sie sowohl einen Schlüssel zur Identifizierung des Datensatzes, als auch jede Menge Attribute für das Update. Dafür lesen Sie die it_keytab analog zur GET_ENTITY Methode aus und die übergebenen Daten analog zu CREATE_ENTITY. Nach welchem Schema Sie das Update nun in Ihrem Backend durchführen, ist Ihnen überlassen. Falls Sie sich das Auslesen aus der Keytab an dieser Stelle sparen wollen, finden Sie den Schlüssel auch in den ausgelesenen Attributen Ihrer Entität.

Sie könnten nun auch analog zu vorigen Methoden Rückmeldung zum Erfolg der Methode geben, aber auch ohne einen Rückgabewert zu befüllen läuft der erfolgreiche HTTP-Request auf eine grüne 204:

UPDATE_ENTITY

Zum Testen im Gateway-Client habe ich mir analog zu CREATE_ENTITY einen Datensatz vorbereitet, die HTTP-Methode auf „Put“ gestellt und in der URL wieder eine ID mitgeliefert:

Entity Updated

DELETE_ENTITY

Der letzte ODATA-Service befasst sich mit dem Löschen eines Datensatzes. Hierfür müssen Sie lediglich eine ID übergeben. Das Vorgehen in der DELETE_ENTITY-Methode ist daher wieder ein Auslesen der it_keytab analog zu GET_ENTITY. Bei Bedarf können Sie auch hier wieder Informationen über den gelöschten Datensatz ans Frontend übergeben, andernfalls kommen Sie analog zum Update auf den HTTP-Code 204:

DELETE_ENTITY

Zum Testen im Gateway-Client setzen Sie die HTTP-Methode auf „Delete“ und wählen die URL mit ID analog zu GET_ENTITY:

Delete Entity Gatway-Client

Nun haben Sie alle 5 ODATA-Services kennen gelernt, für unser Beispiel implementiert und im Gateway-Client getestet. Im nächsten Teil der Reihe werden Sie diesen ODATA-Service weiterverwenden und die entsprechende Fiori-Anwendung dafür entwerfen.

Wenn der OData Service zu Fehlern führt [Whitepaper]

Mit der App-Entwicklung in Fiori hat sich eine Sache grundlegend geändert: Es ist ein Zugriff über die OData Services notwendig.

Hat es Ihnen gefallen?

Wenn es Ihnen gefallen hat, schauen Sie doch gerne bei der ODATA-Grundlagenreihe vorbei. Dort gibt es weitere Grundlagen praktisch erklärt!

SAPUI5: ODATA Grundlagen in der praktischen Verwendung

Florian Tent

Florian Tent

Als SAP Consultant bei der mindsquare begeistere ich mich für das Verstehen und Lösen von Problemen. Die Beratung im Personalwesen sticht für mich aufgrund des hohen Kommunikationsanteils und der großen Anzahl betroffener Mitarbeiter besonders heraus!

Sie haben Fragen? Kontaktieren Sie mich!



Das könnte Sie auch interessieren


Mehr von unseren Partnern


Schreiben Sie einen Kommentar

Bitte füllen Sie alle mit * gekennzeichneten Felder aus. Ihre E-Mail Adresse wird nicht veröffentlicht.





Angebot anfordern
Preisliste herunterladen
Expert Session
Support