ODATA Grundlagen: Tricks zur Steuerung der Backend-Aufrufe
Warum steht hier noch der alte Wert? Wieso werden so viele Anfragen ans Backend gesendet? Wenn Sie sich mit OData Entwicklung befassen, werden Sie sich vermutlich bereits ähnliche Fragen gestellt haben.
Heute erfahren Sie, wie ich mit der Problematik umgehe. Ich erläutere Ihnen die wichtigsten Punkte sowie meine persönlichen Tricks zur Steuerung der Backend-Aufrufe.
Inhalte
- Backend Aufrufe analysieren
- Implizite und explizite Aufrufe
- Möglichkeiten zur Steuerung: Beispiel read Model
- Model und Navigation
- Asynchronität der Aufrufe
Backend Aufrufe analysieren
Zu Beginn möchte ich Ihnen zwei schnelle Möglichkeiten an die Hand geben, um einen genauen Überblick über die tatsächlichen Backend Aufrufe Ihrer Anwendung zu gewinnen. In der Regel findet die Kommunikation über die OData Standard Methoden statt. Dafür sollten einige der Methoden GET_ENTITYSET, GET_ENTITY, UPDATE_ENTITY, CREATE_ENTITY und DELETE_ENTITY in Ihrer erweiterten Data Provider Class (_EXT) redefiniert sein. Mit Rechtsklick oder mit STRG + Linksklick können Sie externe Breakpoints in alle 5 Methoden setzen. Solange Sie ihre Backend Session nicht beenden, springen externe Breakpoints auch bei Aufrufen aus dem Frontend an. Entsprechend wird sich der Debugger jedes Mal öffnen, wenn aus dem Frontend ein Aufruf ans Backend geht. Sie können dann natürlich auch direkt sehen, in welcher Methode Sie sich befinden und welche Daten für den Aufruf übergeben werden.
Je komplexer die Anwendung wird, desto problematischer wird dieser Weg allerdings. Wenn beim Laden der Anwendung bereits 10 oder 15 Anfragen ans Backend gestellt werden, ist die maximale Anzahl an SAP Modi für die Debugger schnell überschritten. Eine weitere Möglichkeit bietet daher der Chrome Debugger. Über F12 aufgerufen liefert der Reiter “Netzwerk” detaillierte Informationen über die HTTP Anfragen. Natürlich entstehen beim Aufbau der Seite zahlreiche Anfragen. Die Kunst ist es hierbei, unsere OData Aufrufe herauszupicken.
Hier können Sie einerseits Informationen über die URL bekommen, damit Sie die Anfrage im Gateway-Client nachstellen können. Außerdem können Sie in den weiteren Reitern auch noch das genaue Ergebnis aus dem Backend sowie die vollständige HTTP Antwort einsehen. Wenn Sie oben links im Debugger den Filter auf den Namen Ihres OData Service stellen, sollten Sie alle Ihre OData Aufrufe auf einen Blick sehen.
Implizite und explizite Aufrufe
Grundsätzlich können OData Anfragen an das Backend sowohl aus der View, als auch aus dem Controller heraus initiiert werden. Für einfache und statische Aufrufe eignet sich die View wunderbar. Die OData Aufrufe werden beim Aufbau der View gestartet. Eine Steuerung im zeitlichen Ablauf ist in der XML-View nicht möglich. Ein klassischer Anwendungsfall hierfür ist die Master-Liste in einer Master-Detail Anwendung. Hier soll in der Regel das Ergebnis eines GET_ENTITYSET Aufrufs an ein “List” Control gebunden werden. Der entsprechende OData Aufruf wird direkt in der XML-Datei festgelegt. In diesem Falle wird ein GET_ENTITYSET Aufruf gegen den Entitätstypen “Person” gestartet:
Filter, Sorter und weitere Zusatzinformationen können bei dem Aufruf angereichert werden. Sobald der Pfad oder die Filter allerdings dynamisch gestaltet werden sollen, empfiehlt sich der Aufruf aus dem JavaScript Controller.
Im JavaScript Controller verfügen Sie frei über den Zeitpunkt der Anfrage. Zudem können Sie Pfad, Filter und ähnliches dynamisch zusammenbauen. Allerdings müssen Sie dabei auch manuell festlegen, wie und wofür das Ergebnis des Aufrufs zu verwenden ist. Im unten folgenden Beispiel wird abhängig vom übergebenen Pfad ein GET_ENTITY oder ein GET_ENTITYSET Aufruf ans Backend gestartet:
Allerdings wird das Ergebnis nicht automatisch angezeigt. Durch den Aufruf sind die Daten aus dem Backend geladen und in der Session unter dem gegebenen Pfad abgelegt worden. Hier stehen die Daten Ihnen nun für weitere Verwendung zur Verfügung. Im JavaScript Controller können Sie zudem alle CRUD Methoden des OData-Service ansteuern. Eine genaue Beschreibung hierfür finden Sie in meinem vorigen Blogbeitrag.
Model und Navigation
Das Default Model kann grundsätzlich problemlos von allen verschiedenen Views angesteuert werden. Dementsprechend wird das OData Model auch durch die Navigation erst einmal nicht beeinflusst.
Interessant wird es, wenn Sie von Master auf Detail navigieren, ihr Model aber irgendwie nicht aktuell wird. Besonders wichtig wird dies, wenn Sie beim GET_ENTITYSET Aufruf der Masterliste nur bestimmte Felder übertragen, beim GET_ENTITY Aufruf der Detail Seite allerdings weitere Informationen anzeigen wollen.
Der klassische “bindElement(sPath)” Aufruf für die Detail View kommt hierbei schnell an seine Grenzen. Der Aufruf von bindElement erzeugt nur einen Aufruf ans Backend, wenn zum übergebenen Pfad noch keine Daten im Model vorhanden sind. Wenn Sie folglich mit dem Laden der Masterliste den Pfad zur Entität schon mit Überblicks-Informationen befüllen, wird bindElement diese Daten finden und keinen Aufruf ans Backend starten. In der Detail Ansicht sind dann auch nur die Daten befüllt, die Ihr mit GET_ENTITYSET befüllt habt.
Der Aufruf oModel.read(sPath) hingegen erzeugt auch einen Aufruf ans Backend, wenn bereits Daten hinterlegt sind. Die hinterlegten Daten werden dann durch den Aufruf überschrieben. Die read() Methode sollte allerdings nur in Ausnahmefällen verwendet werden und wird hier zur Veranschaulichung der Problematik verwendet.
In diesem Beispiel würden zuerst mit dem bindElement alle bereits vorhandenen Informationen an die View gebunden werden. Sobald das Ergebnis des OData Aufrufs durch OModel.read(sPath) angekommen ist, werden die Informationen auf der Detail View entsprechend aktualisiert.
Asynchronität der Aufrufe
Im Beispiel von oben binden Sie erst vorhandene Daten an die View und aktualisieren diese anschließend, sobald das Ergebnis des OData Aufrufs angekommen ist. Für den Anwender wäre dieses Verhalten sicherlich irritierend. Ähnliche Situationen kommen häufig vor: Sie haben einen asynchronen OData Aufruf, brauchen die Daten aber für folgende Aktionen.
Viele lösen diese Herausforderung über Callbacks. Sie nutzen also den “success” Parameter Ihres OData Aufrufs, um dort dann mit dem Ergebnis weiter zu arbeiten. Für Kleinigkeiten ist dieses Vorgehen auch durchaus empfehlenswert. Beispielsweise eine Rückmeldung für den Anwender, ob seine Anfrage erfolgreich war, wird häufig über die Callbacks umgesetzt. Für die Steuerung Ihres Programmablaufs allerdings ist dieses Vorgehen nicht empfehlenswert. Ihr Code wird dadurch sehr schnell sehr kompliziert. Wartbarkeit und insbesondere Wiederverwendbarkeit gehen dadurch verloren.
Eine Möglichkeit zur Steuerung des Programmablaufs bietet das Promise. Hierbei legen Sie sich eine Promise Variable an, die Ihren Status ändert, sobald das Ergebnis des Aufrufes angekommen ist. Die Promise.then() Funktion wird aufgerufen, sobald das Ergebnis des Promise angekommen ist. Mit Promise.all() können Sie sogar auf das kombinierte Ergebnis mehrerer Aufrufe warten.
Für meinen Anwendungsfall von weiter oben, habe ich ein Promise eingebaut. So stelle ich sicher, dass die Daten erst nach dem erfolgreichen Aufruf ans Backend in der View angezeigt werden:
Die Variable promLoadData ist hierbei mein Promise, welches auf dem oModel.read(sPath) Aufruf basiert:
Sobald der HTTP Request abgeschlossen ist, reagiere ich auf das Ergebnis und ändere den Status des Promise. Dementsprechend wird der Aufruf promLoadData.then() in der Abbildung oben erst gestartet, sobald der GET_ENTITY Aufruf ans Backend abgeschlossen ist. Allerdings wird das Promise noch nicht von allen Versionen des Internet Explorers unterstützt. Es empfiehlt sich daher vorher zu schauen, ob die Nutzer Ihrer Anwendung davon betroffen sein könnten.
Hat es Ihnen gefallen?
Hat Ihnen der Beitrag gefallen? Ich freue mich über Feedback und Anregungen für weitere Beiträge. Kommentieren Sie dafür einfach unter dem Blog oder schreiben Sie mir einfach eine E-Mail.
Schnittstelle zwischen SAP HCM und beliebigem System für reibungslose Datenübertragung
Viele Kunden nutzen Cloud HCM Lösungen kommen aber nicht von der onPremise Variante los.Eine Schnittstelle kann hier die Lösung sein.