Custom Entity

Im ABAP RESTful Application Programming Model (RAP) bilden wir Business Objects normalerweise auf Basis von CDS View Entities und persistenten Tabellen ab. Doch es gibt Situationen, in denen die Daten gar nicht in der SAP-Datenbank liegen. Das ist zum Beispiel der Fall, wenn Informationen aus einem externen Service, aus einer RFC-Schnittstelle oder aus einer Berechnung „on the fly“ bereitgestellt werden sollen. Für solche Szenarien gibt es die Custom Entity.


Definition Custom Entity

Eine Custom Entity ist eine virtuelle Datenquelle. Sie sieht aus wie ein CDS View, besitzt aber keine FROM-Klausel und keine eigene Persistenz. Stattdessen muss der Entwickler selbst bestimmen, wie die Daten bereitgestellt werden.

Die Definition einer Custom Entity erfolgt in CDS. Im folgenden Beispiel wird eine Flugliste definiert:


@EndUserText.label: 'Flugliste (Custom Entity)'
define custom entity ZCE_FLIGHT_LIST
{
  key carrier_id   : abap.char(3);
  key connection_id: abap.numc(4);
      city_from    : abap.char(20);
      city_to      : abap.char(20);
      flight_date  : abap.dats;
      price        : abap.curr(10,2);
}
Wichtig ist, dass Schlüsselattribute zwingend erforderlich sind, auch wenn keine Tabelle im Hintergrund existiert.

Behavior Definition

Damit RAP die Custom Entity nutzen kann, wird eine Behavior Definition benötigt. Diese legt fest, welche Operationen erlaubt sind. Im Beispiel werden ein einfaches Lesen sowie eine Action „book“ vorgesehen.


define behavior for custom entity ZCE_FLIGHT_LIST
implementation in class ZBP_CE_FLIGHT_LIST unique
{
  retrieve;
  action ( features : instance ) book;
}

Standard-Bausteine für Behavior Definition für Custom Entities (BDEF)

1. retrieve

Wird immer benötigt, um Daten überhaupt lesbar zu machen.

retrieve;

Implementierung im Handler über IF_RAP_QUERY_PROVIDER~select.

2. action

Dient dazu, eigene Operationen auf einer Instanz oder statisch auszuführen, z. B. „Buchen“ oder „Refresh“.

action ( features : instance ) book;
action ( features : static ) refresh;

Implementierung im Handler über IF_RAP_ACTION_HANDLER~execute.

3. function import

Ähnlich wie Actions, aber ohne Bezug zu einer bestimmten Entity. Eher wie „freie Funktionen“ auf Service-Ebene.

function import getStatistics result [1] ZCE_FLIGHT_STATS;

Implementierung ebenfalls über IF_RAP_ACTION_HANDLER~execute, jedoch als Funktionsaufruf ohne Instanzbindung.

4. draft

Erlaubt Draft-Funktionalität, muss komplett selbst programmiert werden.

draft;

Implementierung über Methoden für prepare, activate, discard in der Behavior-Implementierungsklasse.

5. validation

Definiert Prüfungen, die auf Änderungen angewendet werden.

validation validate_price on modify { field price; }

Implementierung im Handler über IF_RAP_VALIDATION~execute.

6. determination

Definiert Regeln, die beim Anlegen oder Ändern automatisch gesetzt werden.

determination set_defaults on modify { field city_from; }

Implementierung im Handler über IF_RAP_DETERMINATION~execute.

7. authorization

Regelt, welche Operationen erlaubt sind und prüft Berechtigungen.

authorization master ( instance );

Implementierung im Handler über IF_RAP_AUTHORIZATION~get_instance_authorizations.

Vergleich: Custom Entity vs. Root Custom Entity

Merkmal Custom Entity Root Custom Entity
Rolle im BO Baustein oder Child Einstiegspunkt (Root)
Persistenz Keine Keine
Pflichtoperation retrieve retrieve, optional draft
Erweiterungen action, function import action, function import, draft, validation, determination, authorization
Draft Nicht verfügbar Verfügbar (manuell implementiert)
Navigation Kann Child sein Kann Child Entities haben
OData Exposition Nur eingebunden, nicht Root Einstiegspunkt im Service

Behavior-Implementation-Klasse

Die eigentliche Logik steckt in der Behavior-Implementation-Klasse. Dort liefert die Methode if_rap_query_provider~select die Daten zurück. Diese können aus einem Service, einer Berechnung oder – wie hier – einfach als Dummy-Werte erzeugt werden.


CLASS zbp_ce_flight_list DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_rap_query_provider.
    INTERFACES if_rap_action_handler.
ENDCLASS.

CLASS zbp_ce_flight_list IMPLEMENTATION.

  METHOD if_rap_query_provider~select.
    DATA lt_result TYPE TABLE OF zce_flight_list.

    APPEND VALUE #( carrier_id    = 'LH'
                    connection_id = '0405'
                    city_from     = 'Berlin'
                    city_to       = 'New York'
                    flight_date   = sy-datum + 7
                    price         = '899.00' ) TO lt_result.

    APPEND VALUE #( carrier_id    = 'AF'
                    connection_id = '1234'
                    city_from     = 'Paris'
                    city_to       = 'Tokyo'
                    flight_date   = sy-datum + 10
                    price         = '1299.00' ) TO lt_result.

    io_response->set_data( lt_result ).
  ENDMETHOD.

  METHOD if_rap_action_handler~execute.
    LOOP AT it_requests ASSIGNING FIELD-SYMBOL(<req>).
      APPEND VALUE #( %key   = <req>-keys[ 1 ]
                      %param = VALUE zce_flight_list(
                                carrier_id    = <req>-keys[ 1 ]-carrier_id
                                connection_id = <req>-keys[ 1 ]-connection_id
                                city_from     = 'Booking Confirmed'
                                city_to       = ''
                                flight_date   = sy-datum
                                price         = '0.00' ) ) TO et_results.
    ENDLOOP.
  ENDMETHOD.

ENDCLASS.

Service Definition

Damit die Custom Entity nach außen sichtbar wird, benötigt man eine Service Definition. Diese legt fest, dass die Entity exponiert wird:

define service ZUI_FLIGHT_CE {
  expose ZCE_FLIGHT_LIST;
}

Unterschied „update“ vs. „action“

update

Wird im RAP automatisch vom Framework aufgerufen, wenn ein Client ein PATCH oder PUT auf eine Entity macht.
- Erwartung: partielles Update von einzelnen Attributen (Felder der Entity selbst).
- Beispiel: PATCH /ItemItm(...){ "CharcValue": "RED" }
- Limitiert auf einzelne Zeilen, keine komplexe Semantik.


action

Frei definierbare Operation, die du selber im Behavior deklarierst.
- Kann komplexe Logik enthalten, mehrere Tabellen/Instanzen betreffen, BAPIs aufrufen usw.
- Wird per POST .../Entity(...)/ActionName aufgerufen.
- Parameter können Strukturen oder Tabellen sein.
- Ergebnis kannst du selbst definieren (z. B. die geänderte Entity zurückgeben).