This is a test message to test the length of the message box.
Login
|
ABAP RAP CDS Pattern
Erstellt von Software-Heroes

RAP - CDS Pattern

220

Wie geht eigentlich das CDS Pattern und was hat CDS-only damit zu tun? In diesem Artikel schauen wir auf die Architektur und Nutzung des Patterns.

Werbung


In diesem Artikel schauen wir uns das CDS Pattern an, wie du es implementieren und sinnvoll in deine Entwicklung einbinden kannst.

 

Einleitung

Das ABAP RESTful  Application Programming Model ist das neue Modell in ABAP, um Cloud Ready und Clean Core Anwendungen zu erstellen. Mit RAP lassen sich neben Anwendungen, auch Schnittstellen für den internen und externen Gebrauch zur Verfügung stellen. Mit den neusten Features ist RAP sehr flexibel was den Aufbau und die Nutzung angeht, weshalb wir die Anwendungen in verschiedene Pattern aufteilen möchten.

 

Aufbau

Das "CDS Pattern" wird so genannt, weil wir die CDS-only Mechanismen der Entwicklung nutzen. Wir verzichten dabei auf die klassischen Instrumente, wie Datenelemente, Domänen und DDIC Tabellen, um unser Datenmodell zu erstellen. Damit ersparen wir uns verschiedene Mappings bei der Nutzung der Daten in unserem Modell. Zur Einleitung noch die Legende für das Modell.

 

Dazu die folgenden Merkmale zur Abgrenzung:

  • Datenquelle des Models sind Table Entities (Nachfolger der DDIC Tabellen)
  • Interface Layer (CDS) wird nicht benötigt, Verhalten und Verbindungen können auf CDS Ebene modelliert werden
  • Nutzung von CDS-only (Table Entity, Simple Types, Aspects)
  • Mapping in Verhaltensdefinition nicht mehr nötig

 

 

Mit der Table Entity können wir unser Datenmodell und die Beziehungen bereits auf dieser Ebene definieren und müssen das nicht auf Interface Ebene machen. Daher können wir uns diesen Layer sparen und damit Objekte. Der Layer bleibt aber optional, wenn du vielleicht ein Mapping von Elementen machen möchtest oder andere Besonderheiten hast.

 

Beispiel

Dazu modellieren wir unsere Anwendung auf dem Datenmodell unserer Core Data Service Reihe und verwenden die Rechnung (Invoice) und die Position um ein RAP Objekt zu erstellen.

 

Datenmodell

Da wir keine klassische Tabelle haben, legen wir zwei Table Entities im System an. In diesem Fall arbeiten wir mit eingebauten Datentypen und verzichten der Einfachheit halber auf Simple Types. In der Entität müssen wir ebenfalls die neuen Datentypen für Datum und Uhrzeit verwenden, da die Alten nicht mehr unterstützt werden.

@ClientHandling.type: #CLIENT_DEPENDENT
@AbapCatalog.deliveryClass: #APPLICATION_DATA
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS-P: Invoice'
define root table entity ZBS_T_CDSPatternInvoice
{
  key DocumentNumber     : abap.char(8);
      DocumentDate       : abap.datn;
      DocumentTime       : abap.timn;
      PartnerNumber      : abap.char(10);
      @Semantics.user.createdBy: true
      LocalCreatedBy     : abp_creation_user;
      @Semantics.systemDateTime.createdAt: true
      LocalCreatedAt     : abp_creation_tstmpl;
      @Semantics.user.localInstanceLastChangedBy: true
      LocalLastChangedBy : abp_locinst_lastchange_user;
      @Semantics.systemDateTime.localInstanceLastChangedAt: true
      LocalLastChangedAt : abp_locinst_lastchange_tstmpl;
      @Semantics.systemDateTime.lastChangedAt: true
      LastChangedAt      : abp_lastchange_tstmpl;

      _Position          : composition of exact one to many ZBS_T_CDSPatternPosition;
}

 

Das Mandanten-Handling passiert über die Annotation im View. Zusätzlich können wir auch direkt die Beziehung im View modellieren. Bevor wir den View aber aktivieren können, sollten wir zuvor noch die Position anlegen. Hier definieren wir auch die entsprechenden Felder, müssen allerdings noch zusätzlich die Einheit für die Menge aufnehmen, da Assoziationen an dieser Stelle nicht möglich sind.

@ClientHandling.type: #CLIENT_DEPENDENT
@AbapCatalog.deliveryClass: #APPLICATION_DATA
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'CDS-P: Position'
define table entity ZBS_T_CDSPatternPosition
{
  key DocumentNumber   : abap.char(8);
  key PositionNumber   : abap.int2;
      MaterialNumber   : abap.char(5);
      @Semantics.quantity.unitOfMeasure : 'PositionUnit'
      PositionQuantity : abap.quan(10,0);
      PositionUnit     : abap.unit(3);
      @Semantics.amount.currencyCode : 'PositionCurrency'
      PositionPrice    : abap.curr(15,2);
      PositionCurrency : abap.cuky;
      
      _Document : association to parent ZBS_T_CDSPatternInvoice on _Document.DocumentNumber = $projection.DocumentNumber;
}

 

Verhalten

Im Verhalten definieren wir noch zusätzlich Draft, verlinken die Felder und die verschiedenen Draft Actions, da wir einen OData v4 anlegen wollen. Im aktuellen Status können wir leider nur DDIC Tabellen für den Draft anlegen, dass soll Anfang 2026 sich dann ändern. Da wir das Verhalten direkt auf der Table Entity definiert haben, sparen wir uns das Mapping der Entität auf die Datenquelle.

managed implementation in class zbp_bs_cdspattern_invoice unique;
strict ( 2 );
with draft;

define behavior for ZBS_T_CDSPatternInvoice alias Invoice
draft table zbs_cp_invoice_d
lock master total etag LastChangedAt
authorization master ( instance )
etag master LocalLastChangedAt
{
  create ( authorization : global );
  update;
  delete;

  field ( readonly ) DocumentNumber;

  draft action Edit;
  draft action Activate optimized;
  draft action Discard;
  draft action Resume;
  draft determine action Prepare;

  association _Position { create; with draft; }
}

define behavior for ZBS_T_CDSPatternPosition alias Position
draft table zbs_cp_pos_d
lock dependent by _Document
authorization dependent by _Document
{
  update;
  delete;

  field ( readonly ) DocumentNumber, PositionNumber;

  association _Document { with draft; }
}

 

Abschluss

Aktuell werden Table Entities nicht in den RAP Generatoren unterstützt, daher müssen wir das komplette RAP BO per Hand aufbauen. Die restlichen Schritte, wie Projection, Service Definition und Binding können wir dann wie immer definieren. Für das Numbering weichen wir aktuell auf ein Late Numbering aus und implementieren etwas Zusatzlogik. Die weiteren Details zur Implementierung findest du im GitHub Repository im nächsten Kapitel.

 

Test

Nachdem wir dann das UI über die Metadata Extension angelegt haben, können wir die Anwendung testen. Dazu legen wir einen neuen Header an und befüllen die nötigen Informationen.

 

Nach dem Speichern wurde eine neue Nummer vergeben und die Daten auf der Datenbank abgelegt, unsere Anwendung funktioniert nun so weit, wenn auch nicht perfekt.

 

Vollständiges Beispiel

Das vollständige Beispiel findest du bei uns im GitHub Repository und über den Commit findest du alle Änderungen. Innerhalb des Repository befindet sich das Beispiel im Paket ZBS_DEMO_RAP_PATTERN_CDS. Wie bereits oben beschrieben, wirst du das Consumption Model und die Aufrufimplementierung dort nicht finden.

 

Zusammenfassung

Im Grund ist das Pattern sehr ähnlich zum Classic Pattern in der RAP Entwicklung. Dadurch, dass wir aber auf die klassischen Artefakte verzichten, können wir bereits auf Ebene der Table Entity die echten Feldnamen definieren und die Beziehungen innerhalb der Objekte modellieren. Damit können wir uns in den meisten Fällen den Interface Layer sparen und das Verhalten direkt auf die Tabelle setzen. Damit erhalten wir auch Groß- und Kleinschreibung für die Typen, Objekte und Felder und haben im Gegensatz zur Tabelle, mehr Zeichen für die Benennung.

Allerdings funktioniert das Modell noch nicht zu 100% im aktuellen Zustand. Simple Types mit ENUMs werden noch nicht auf Ebene der UI und RAP unterstützt und Draft ist zwar möglich, verwendet aber immer noch eine klassische Tabelle. Mehr der neuen Features werden in 2026 kommen, um das CDS Pattern zu unterstützen.

 

Fazit

Das CDS Pattern wird in Zukunft immer mehr das Classic Pattern ablösen und vereinfachen. Die Anzahl der Objekte wird sich reduzieren und so werden RAP Objekte leichter verständlich. Da wir auf Tabellenebene bereits Berechtigungsprüfungen umsetzen können, wird das Modell für Lesezugriffe auch etwas sicherer.


Enthaltene Themen:
RAPBTPPatternCDSCDS-only
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Dienstag und 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.


Recycling Heroes - Kontakt App

Kategorie - ABAP

In diesem Tutorial modellieren wir eine RAP Anwendung von der Datenbank, über das Modell und das UI, bis zum Deployment und Bereitstellung im System. Damit solltest du den vollen Entwicklungszyklus für modernen ABAP Cloud Anwendungen lernen.

25.11.2025

RAP - EML Varianten

Kategorie - ABAP

Wenn du EML verwendest, um mit dem ABAP RESTful Application Programming Model zu interagieren, stehen dir aktuell mehrere Varianten zur Verfürgung. Schauen wir sie uns einmal im Detail an.

16.09.2025

RAP - Generator (from Scratch)

Kategorie - ABAP

Deine Entwicklung mit RAP fühlt sich manchmal sehr langsam an? Generatoren nehmen dir die Arbeit ab, um den eigentlich Stack aufzubauen und wiederkehrende Arbeit abzunehmen.

05.08.2025

RAP - Aktion (Verarbeitungsoptionen)

Kategorie - ABAP

Wie aktivierst du eigentlich den Multi-Select in RAP und steuerst die verschiedenen Verarbeitungsoptionen? Hier schauen wir uns die verschiedenen Möglichkeiten im Framework an.

01.08.2025

RAP - Custom Entity mit Aktion

Kategorie - ABAP

Wie kannst du eigentlich in einer Custom Entity eine Action sauber implementieren, um am Ende auch das UI zu aktualisieren? Schauen wir uns die verschiedenen Schritte im Detail an.

29.07.2025