This is a test message to test the length of the message box.
Login
ABAP RAP Deep Action
Erstellt von Software-Heroes

RAP - Deep Action in OData v4

107

In diesem Artikel schauen wir uns einmal Aktionen mit tiefen Strukturen an, wie wir sie erzeugen und Daten an einen API Endpunkt übergeben können.

Werbung


In diesem Szenario erweitern wir unsere komplexe Entität um eine zusätzliche Aktion. In diesem Fall wollen wir tiefe Daten (Kopf und Position) an die Aktion übergeben, um damit eigenen Code auszuführen und mit dem gesamten Datenpaket arbeiten zu können. Danke an Saptarshi für die Frage.

 

Einleitung

In bestimmten Situationen möchten wir nicht nur einzelne Daten in unser RAP Objekt bekommen, sondern tiefe Strukturen, in denen alle Daten bereits enthalten sind. So können wir die Daten auf Vollständigkeit prüfen, verschiedene SAP APIs im System triggern oder auch HTTP Schnittstellen ansprechen. Als Entwickler erhältst du damit die volle Kontrolle bei der Verarbeitung.

 

Voraussetzungen

Entsprechend gibt es auch Voraussetzungen, damit so eine Aktion funktioniert. Wir möchten die Aktion in einer Web API implementieren, um sie von außen aufrufen zu können. Mit tiefen Strukturen können wir allerdings nur in OData Version 4 arbeiten, dies ist die minimale Version für so eine Umsetzung. Bei OData v2 kommt es bei der Freigabe zu einem Fehler und dem Hinweis auf die Unterstützung.

 

Aufbau

Im ersten Schritt erweitern wir das bestehende RAP Objekt um eine zusätzliche Aktion.

 

Entitäten

Bevor wir allerdings die Aktion implementieren können, müssen wir die Strukturen dafür anlegen und die Felder definieren, die wir in unseren Service erhalten wollen. Legen wir dazu die abstrakte Entität an, die die Daten entgegennehmen soll.

@EndUserText.label: 'Create Invoice'
define root abstract entity ZBS_S_RAPCreateInvoice
{
  key DummyKey  : abap.char(1);
      Document  : abap.char(8);
      Partner   : abap.char(10);
      _Position : composition [0..*] of ZBS_S_RAPCreatePosition;
}

 

Der DummyKey wird für die Verknüpfung der beiden Entitäten (Kopf und Position) benötigt. Über die Composition "_Position", definieren wir die Positionen, die mit übergeben werden. Die Entität für die Positionen sieht nun entsprechend so aus:

@EndUserText.label: 'Create Position'
define abstract entity ZBS_S_RAPCreatePosition
{
  key DummyKey          : abap.char(1);
      Material          : abap.char(5);
      @Semantics.quantity.unitOfMeasure : 'Unit'
      Quantity          : abap.quan(10,0);
      Unit              : abap.unit(3);
      @Semantics.amount.currencyCode : 'Currency'
      Price             : abap.curr(15,2);
      Currency          : abap.cuky;
      _DummyAssociation : association to parent ZBS_S_RAPCreateInvoice on $projection.DummyKey = _DummyAssociation.DummyKey;
}

 

Entsprechend legen wir auch hier einen DummyKey an und definieren die Felder die wir auf Positionsebene benötigen. Über die Assoziation stellen wir die Beziehung zum Kopf bzw. den Rechnungen her. Zum Abschluss benötigen wir noch eine Verhaltensdefinition, um das Beziehungen untereinander zu definieren.

abstract;
strict( 2 );
with hierarchy;

define behavior for ZBS_S_RAPCreateInvoice alias Invoice
{
  field ( suppress ) DummyKey;
  association _Position;
}

define behavior for ZBS_S_RAPCreatePosition alias Position
{
  field ( suppress ) DummyKey;
}

 

Besonderheiten sind hier der Typ "abstract", der View benötigt auch den Zusatz "with hierarchy" um sauber zu funktionieren. Solltest du den Zusatz vergessen, erscheint beim Einbinden der Aktion der Fehler und weist darauf hin. Zum Abschluss unterdrücken wir noch den DummyKey, da wir diesen in den Daten nicht benötigen und anbieten wollen. Der Rest der Verhaltensdefinition entspricht dem Standard.

 

Verhaltensdefinition

Im nächsten Schritt können wir nun die Verhaltensdefinition erweitern und die neue Aktion anlegen. Fangen wir also im Interface an und definieren eine statische Aktion in der Entität "Invoice" auf oberster Ebene.

static action CreateInvoiceDocument deep parameter ZBS_S_RAPCreateInvoice;

 

Eine statische Aktion benötigen wir, da wir ohne Referenz zu einem Datensatz arbeiten wollen. Über den Zusatz DEEP geben wir an, dass es sich um einen tiefen Datentyp handelt. Über STRG + 1 können wir dann die Methode in der Verhaltensimplementierung anlegen lassen. Zum Abschluss erweitern wir die Consumption Sicht, sodass die Aktion in der API zur Verfügung steht. 

use action CreateInvoiceDocument;

 

Web API

Um von außen auf die API zugreifen zu können, legen wir ein Service Binding vom Typ API und OData v4 an.

 

Nun müssen wir ein Communication Scenario anlegen und die entsprechende Konfiguration im ABAP Environment durchführen. Wie das Schritt für Schritt funktioniert, kannst du in diesem Artikel nachlesen.

 

Ausführung - ABAP

Starten wir den ersten Aufruf mit EML und probieren die Daten an die Aktion im System zu übergeben. Dazu legen wir eine interne Tabelle für die Aktion an, befüllen diese mit Daten und übergeben sie an das RAP Business Objekt.

DATA lt_document TYPE TABLE FOR ACTION IMPORT ZBS_R_RAPCInvoice~CreateInvoiceDocument.

lt_document = VALUE #( ( %cid   = to_upper( cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ) )
                         %param = VALUE #( Document  = 'TEST'
                                           Partner   = '1000000004'
                                           _position = VALUE #(
                                               Unit     = 'ST'
                                               Currency = 'EUR'
                                               ( Material = 'F0001' Quantity = '2' Price = '13.12' )
                                               ( Material = 'H0001' Quantity = '1' Price = '28.54' ) ) ) ) ).

MODIFY ENTITIES OF ZBS_R_RAPCInvoice
       ENTITY Invoice
       EXECUTE CreateInvoiceDocument FROM lt_document
       FAILED DATA(ls_failed_deep)
       REPORTED DATA(ls_reported_deep).

 

Damit ist der erste Test abgeschlossen und wir können den Weg über die API testen.

 

Ausführung - POSTMAN

Als zweiten Test wollen wir den Endpunkt im System per POSTMAN aufrufen, um so die API und die Übergabe zu testen. Dazu müssen wir zwei Schritte durchführen, einmal einen CSRF Token erstellen (GET) und einmal die Aktion auslösen (POST), wo wir dann auch die Daten übergeben.

 

Collection

Legen wir dazu in POSTMAN eine neue Collection (Ordner) an, unter dem Reiter "Authorization" stellen wir auf "Basic Authentication" um, damit erhalten wir die Möglichkeit uns per User und Passwort am Endpunkt anzumelden. Damit erhalten alle Requests unter der Collection diese Methode und wir müssen uns nicht mehr um die Anmeldung pro Anfrage kümmern.

 

Hinweis: Die Eintragung von User und Passwort dient lediglich zur Demonstration, im Normalfall werden solche Informationen in Environment Variablen abgelegt, wo sie auch verschlüsselt werden.

 

CSRF Token

Bevor wir die Aktion ausführen können, benötigen wir einen Token. Dazu legen wir unter unserer Collection einen neuen GET Request an und verwenden dabei den Endpunkt unseres Services, diese findest du zum Beispiel im Communication Arrangement im ABAP Environment, wo wir das Szenario eingerichtet haben.

 

Im Header geben wir noch das Feld "x-csrf-token" mit dem Wert "fetch" mit. Damit weiß der Endpunkt, dass wir einen neuen Token von ihm anfordern. Nach dem Ausführen findest du den Token im Antwort-Header im Feld "x-csrf-token".

 

Aktion

Nun möchten wir die eigentliche Aktion ausführen, dazu benötigen wir zuerst den Endpunkt unserer Aktion aus dem Service. Dieser setzt sich aus verschiedenen Bestandteilen zusammen:

<SERVICE-URL>/<ENTITY>/<NAMESPACE>.<ACTION>

 

Die Service URL haben wir bereits zuvor verwendet für den Token, es folgt dann die Entität, an der wir die Aktion definiert haben. Den Namespace findest du in den Metadaten des Service. Der hintere Teil der URL würde dann wie folgt aussehen:

/Invoice/com.sap.gateway.srvd_a2x.zbs_rapc_invoice.v0001.CreateInvoiceDocument

 

Wir erstellen nun einen POST Request und geben im Header den Token sowie den Content-Type mit.

 

Im Body geben wir unsere Daten mit, die wir an den Endpunkt übergeben wollen, als Format verwenden wir JSON. Hier darauf achten, dass die Zahlen auch wirklich im Zahlenformat übergeben werden. Die Daten werden als Objekt übergeben, wobei die Assoziation "_Position" aus deinem Array besteht, welches wiederum Objekte enthält.

 

Debugging

Damit wir prüfen können, ob der Aufruf klappt, möchten wir die Daten in der Implementierung debuggen. Dazu müssen wir einen Breakpoint für den technischen User setzen, da dieser den Code ausführt. In den ABAP Development Tools müsste du dazu in die "Properties" des ABAP Projekts gehen. Unter dem Punkt "ABAP Development -> Debug" findest du die Einstellungen, um einen anderen User zu debuggen. Hier kannst du über die Suche den Communication User (CC) finden, der Named-User wird nur für den API Zugriff benötigt.

 

Führen wir nun die Anfrage aus, dann öffnet sich der Debugger und über die Importvariablen können wir auf die Informationen zugreifen.

 

Nun kannst du die weitere Implementierung frei übernehmen und nach deinen Wünschen gestalten.

 

Vollständiges Beispiel

Alle durchgeführten Änderungen an den Objekten und die neuen Objekte findest du im Commit des GitHub Repository, falls du die einzelnen Schritte nachstellen möchtest oder dir noch Informationen fehlen.

 

Fazit

Die Implementierung einer Aktion mit tiefer Struktur kann sich etwas speziell anfühlen, wenn es um die Definition der abstrakten RAP Entität geht. Die eigentliche Implementierung und der Aufruf befindet sich dann allerdings im RAP Standard.

 

Quelle:
SAP Help - Input Parameter (Deep)


Enthaltene Themen:
RAPBTPActionDeep
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


RAP - Custom Entity Wertehilfe (Deep Dive)

Kategorie - ABAP

Mit der Custom Entity hast du in RAP die meisten Freiheiten in der Entwicklung von ABAP Cloud Anwendungen, doch wie sieht es mit potentiellen Fehlern aus?

12.07.2024

BTP - Anbindung On-Premise (Consumption Model v2)

Kategorie - ABAP

In diesem Artikel wollen wir noch einmal einen Update zur Anbindung von On-Premise Systemen geben und wie dies mit einem Communication Arrangement durchgeführt wird.

15.12.2023

RAP - App Count anzeigen (Kachel)

Kategorie - ABAP

In diesem Beispiel geht es um die Anzeige eines Zählers auf der Kachel einer Fiori Elements Anwendung und wie sich so etwas umsetzen lässt.

06.10.2023

RAP - Generator (Fiori)

Kategorie - ABAP

In diesem Artikel schauen wir uns den komplexeren RAP Generator als Fiori Elements Anwendung an und welche Vorteile du damit hast.

15.09.2023

RAP - Generator (ADT)

Kategorie - ABAP

Schauen wir uns heute den RAP Generator an, der bereits in die ABAP Development Tools integriert ist und wie du damit ganz leicht neue RAP Apps aufbauen kannst.

08.09.2023