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

RAP - Generierung mit Template

159

Die Generatoren in RAP sind mächtig, wenn es um die schnelle Bereitstellung von RAP Objekten geht. Über Templates kannst du die Entitäten noch einmal schneller anlegen, wenn du eine Schulung machst.

Werbung


In diesem Artikel generieren wir uns im ersten Schritt die Templates und erzeugen uns daraus ein neues RAP Objekt, welches als Grundlage für folgenden Artikel wird.

 

Einleitung

Über die verschiedenen RAP Generatoren haben wir bereits in unterschiedlichen Artikeln berichtet. Egal ob der klassische Generator, die Fiori App, die Business Configuration oder der neue Generator from Scratch, alle generieren am Ende ein RAP Objekt. Hast du dich ausreichend mit RAP und der Entwicklung beschäftigt, würden wir dir immer die Generatoren empfehlen, einfach um Zeit zu sparen und wiederholende Arbeiten zu reduzieren.

 

Datenmodell

Dabei erstellen wir eine Anwendung mit einem neuen Datenmodell, um einige Use-Cases und Implementierungen durchführen zu können. Dabei erstellen wir eine Umsatz App die eng verknüpft ist mit unserem CDS Datenmodell, welches wir auch bereits schon für andere Apps verwendet haben. Auf oberster Ebene gibt es einen Umsatz pro Partner den wir pflegen können. Dort werden auch Abweichungen eingetragen in Form von einer Währung oder einem Prozentsatz. Darunter haben wir eine Entität für Material, dass beim Verkauf beteiligt war, die eigentlichen Verkäufer mit ihrem Anteil und eine Information, die mehrsprachig gepflegt wird.

 

 

Die Beziehungen Partner und Material stammen aus dem CDS Modell, der Business User und die Sprache aus dem Standard im System. Hier beziehen wir bestimmte Daten aus dem System.

 

Generierung

In diesem Kapitel kümmern wir uns um die Generierung der Artefakte.

 

Generator

Im letzten Artikel hatten wir zusammen einen Generator für DDIC Artefakte gebaut, um uns automatisiert Objekte im System anlegen zu lassen. Da wir für das Datenmodell einige Entitäten, Datenelemente und Domänen benötigen, soll der Generator die Arbeit für uns übernehmen. Grundsätzlich kannst du auch fertige Teile des Datenmodells aus dem GitHub Repository ziehen (siehe unten).

 

Konfiguration

Für die Konfiguration legen wir eine ausführbare Klasse im neuen Paket ZBS_DEMO_RAP_SALES an. Die vollständige Konfiguration findest du in GitHub in der Klasse ZCL_SB_DEMO_RAP_SALES_FIELDS. Dabei verwenden wir die ausführbare Klasse mit XCO Template, da diese am besten mit den XCO Klassen für die Ausgabe zusammenarbeitet. Insgesamt wollen wir vier abstrakte Entitäten anlegen, um diese später als Template zu verwenden:

  • ZBS_S_SASale
  • ZBS_S_SAInfo
  • ZBS_S_SASold
  • ZBS_S_SASeller

 

Anlage

Führen wir nun die Konfiguration aus, dann werden im System die verschiedenen Datenelement und Domänen generiert. Kommt es bei dir zu einem Fehler wegen des Pakets oder des fehlenden Transports, dann kannst du die Informationen noch in der Konfiguration nachtragen.

 

RAP Generator

Führen wir nun im nächsten Schritt den RAP Generator im System aus und verwenden die angelegten Templates für die Generierung unsere RAP BOs.

 

Konfiguration

Wie bereits im passenden Artikel oben beschrieben, starten wir den Generator direkt auf dem Paket. Der Generator from Scratch ist On-Prem erst mit der Version 2025 verfügbar, wir arbeiten aktuell vor allem auf dem ABAP Environment.

 

Dort wählst du den Generator "OData UI Service from Scratch" den wir für die Templates verwenden wollen. Im nächsten Schritt ist bereits dass Paket vorbelegt, daher können wir den Schritt einfach bestätigen und landen bei der Generierung des Objekts. Dann können wir direkt auf den Punkt "Business Object Entities" springen, um unser RAP BO zu definieren. Hier wenden wir die abstrakten Entitäten um die Templates zu befüllen.

 

Das kann einen kurzen Moment dauern, da die Struktur analysiert wird und die Felder direkt alle angelegt werden. Mit den Templates sparen wir uns damit die manuelle Anlage aller Felder, Texte und Beziehungen untereinander. Wurden nun die 4 Knoten definiert, dann können wir zum Punkt "Service Configuration" springen. Wieso eigentlich erst jetzt? Die ROOT Entität überschreibt uns das Feld "ProjectName", welches wir erst am Ende definieren wollen. Hier definieren wir ein Präfix für die Generierung.

 

Generierung

Im nächsten Schritt erhalten wir dann die Liste der Objekte, die generiert werden. Nach einer kurzen Prüfung der vergebenen Namen, können wir dann den Generator starten, der dann einiges an Zeit für die Objekte benötigt.

 

Ist die Generierung der Objekte abgeschlossen erhalten wir eine Info vom System und können zum Service navigieren. Dort aktivieren wir den OData Service und können dann die Fiori Elements Preview anschauen.

 

Analyse

In unseren Templates hatten wir keine Schlüssel definiert. Aktuell generiert der RAP Generator automatisch Schlüssel vom Typ UUID für alle Entitäten und definiert auf dieser Basis auch die Beziehungen der Objekte untereinander. Wenn du Informationen Felder anlegst, solltest du diese Eigenschaft berücksichtigen. Schauen wir uns einmal die Haupttabelle für die Sales an, dann finden wir die UUID als Schlüssel unsere Felder mit den passenden Datenelementen, die Beziehungen der Daten untereinander.

@EndUserText.label : 'Database Table for ZBS_SASALE'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zbs_sasale {
  key client            : abap.clnt not null;
  key uuid              : sysuuid_x16 not null;
  partnernumber         : zbs_demo_sa_partner;
  salesdate             : zbs_demo_sa_date;
  @Semantics.amount.currencyCode : 'zbs_sasale.salescurrency'
  salesvolume           : zbs_demo_sa_amount;
  salescurrency         : zbs_demo_sa_currency;
  @Semantics.amount.currencyCode : 'zbs_sasale.differencecurrency'
  differenceamount      : zbs_demo_sa_amount;
  differencecurrency    : zbs_demo_sa_currency;
  @Semantics.quantity.unitOfMeasure : 'zbs_sasale.differenceunit'
  differencequantity    : zbs_demo_sa_quantity;
  differenceunit        : zbs_demo_sa_unit;
  salecomment           : zbs_demo_sa_comment;
  local_created_by      : abp_creation_user;
  local_created_at      : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;
}

 

Schauen wir uns Core Data Service auf dieser Basis an, dann fallen einige nicht so schöne Dinge auf. Aktuell verwendet der Generator noch die alten Kardinalitäten für die Compositions, hier sollten mittlerweile die sprechenden Namen verwendet werden. Ebenso hat der Generator unsere Feldnamen auf PascalName-Basis ignoriert, wodurch das Datenmodell jetzt nicht ganz so "hübsch" ist. 

@AccessControl.authorizationCheck: #MANDATORY
@Metadata.allowExtensions: true
@ObjectModel.sapObjectNodeType.name: 'ZBS_GlobalSale'
@EndUserText.label: '###GENERATED Core Data Service Entity'
define root view entity ZBS_R_SASALE
  as select from zbs_sasale as SASale
  composition [1..*] of ZBS_R_SAINFO   as _SAInfo
  composition [1..*] of ZBS_R_SASOLD   as _SASold
  composition [1..*] of ZBS_R_SASELLER as _SASeller
{
  key uuid                  as UUID,
      partnernumber         as Partnernumber,
      salesdate             as Salesdate,
      @Semantics.amount.currencyCode: 'Salescurrency'
      salesvolume           as Salesvolume,
      salescurrency         as Salescurrency,
      @Semantics.amount.currencyCode: 'Differencecurrency'
      differenceamount      as Differenceamount,
      differencecurrency    as Differencecurrency,
      @Semantics.quantity.unitOfMeasure: 'Differenceunit'
      differencequantity    as Differencequantity,
      differenceunit        as Differenceunit,
      salecomment           as Salecomment,
      @Semantics.user.createdBy: true
      local_created_by      as LocalCreatedBy,
      @Semantics.systemDateTime.createdAt: true
      local_created_at      as LocalCreatedAt,
      @Semantics.user.localInstanceLastChangedBy: true
      local_last_changed_by as LocalLastChangedBy,
      @Semantics.systemDateTime.localInstanceLastChangedAt: true
      local_last_changed_at as LocalLastChangedAt,
      @Semantics.systemDateTime.lastChangedAt: true
      last_changed_at       as LastChangedAt,
      _SAInfo,
      _SASold,
      _SASeller
}

 

Sprache

Aktuell scheint es ein Problem mit Felder vom Typ SPRAS zu geben. Das Feld wurde bei der Generierung aus der Entität geschmissen und wurde daher nicht beachtet. Daher müssen wir im Nachgang das Feld noch mit in die verschiedenen Objekte aufnehmen.

  • Tabelle - ZBS_SAINFO
  • Core Data Service - ZBS_R_SAInfo, ZBS_C_SAInfo
  • Behavior Definition - ZBS_R_SASale
  • Nachgenerierung der Draft Tabelle

 

Hinweis: Nach der Generierung der Artefakte sollte kein Fehler mehr im Service sein. Um die UI-Annotationen würden wir uns beim nächsten Mal kümmern.

 

Refactoring

Wenn dich die Unschärfen nicht stören (PascalCase der Feldnamen), dann kannst du mit diesem Stand später weiterarbeiten. Wir würden nun das Datenmodell noch einmal säubern und auf einen aktuellen Stand bringen. Die aktuelle Version findest du am Ende in GitHub und kannst das saubere Modell laden oder das Refactoring selbst durchführen. Dabei solltest du dir die Entitäten (Core Data Service), Behavior Definition und Metadata Extensions anschauen. Hier einmal der Auszug nach dem Refactoring, die Kardinalität wurde überarbeitet und PascalCase in den Namen wiederhergestellt.

define root view entity ZBS_R_SASALE
  as select from zbs_sasale as SASale
  composition of exact one to many ZBS_R_SAINFO   as _SAInfo
  composition of exact one to many ZBS_R_SASOLD   as _SASold
  composition of exact one to many ZBS_R_SASELLER as _SASeller
{
  key uuid                  as UUID,
      partnernumber         as PartnerNumber,
      salesdate             as SalesDate,
      @Semantics.amount.currencyCode: 'Salescurrency'
      salesvolume           as SalesVolume,
      salescurrency         as SalesCurrency,
}

 

Daten

Nachdem das Objekt angelegt und generiert wurde, legen wir noch einige Daten an. Dazu definieren wir uns eine Klasse ZCL_BS_DEMO_RAP_SALES_DATA die du bei dir im System ausführen musst, damit die Entitäten mit Daten versorgt werden.

 

Bereinigung

Im ersten Schritt würden wir alle Tabellen bereinigen, damit wir die Datengenerierung mehrfach ausführen können. Dabei solltest du neben den eigentlichen Tabellen auch den Draft bereinigen, da hier ebenfalls alte Bestandteile liegen können, die du nicht gespeichert hast.

DELETE FROM zbs_sasale.
DELETE FROM zbs_sasale_d.
DELETE FROM zbs_sainfo.
DELETE FROM zbs_sainfo_d.
DELETE FROM zbs_saseller.
DELETE FROM zbs_saseller_d.
DELETE FROM zbs_sasold.
DELETE FROM zbs_sasold_d.
COMMIT WORK.

 

Befüllung

Für die Befüllung legen wir uns verschiedene Tabellen an, um die abhängigen Informationen mit einem Aufruf in die Datenbank zu bringen. Da wir in diesem Fall immer über die Root Entität gehen und die unteren Daten per Assoziation einfügen, definieren wir auch unsere Tabellen über diesen Weg.

DATA sales   TYPE TABLE FOR CREATE zbs_r_sasale.
DATA infos   TYPE TABLE FOR CREATE zbs_r_sasale\_SAInfo.
DATA sellers TYPE TABLE FOR CREATE zbs_r_sasale\_SASeller.
DATA solds   TYPE TABLE FOR CREATE zbs_r_sasale\_SASold.

 

Anlage

Die Befüllung der Tabellen findest du im GitHub Repository und die einzelnen Datensätze würden wir hier nicht noch einmal im Detail beschreiben. Zum Abschluss rufen wir über EML die Erzeugung der Instanzen und Tabelleneinträge auf. Auf der Ebene von ROOT haben wir die CID selbst definiert, da wir diese für die Unterentitäten benötigen. Dort übergeben wir über CID_REF die Referenz, um die Datensätze dem Root Eintrag zuzuordnen und stellen die Entitäten selbst auf AUTO FILL CID, womit sich das Framework um die Befüllung der CID im Datensatz kümmert. Um die Datendefinition einfach zu halten, verwenden wir WITH für die Felder. Weitere Details zu den EML Varianten findest du im Artikel.

MODIFY ENTITIES OF zbs_r_sasale
       ENTITY SASale
       CREATE FIELDS ( PartnerNumber SalesDate SalesVolume SalesCurrency SaleComment DifferenceAmount DifferenceCurrency )
       WITH sales

       ENTITY SASale
       CREATE BY \_SAInfo AUTO FILL CID FIELDS ( Language TextInformation )
       WITH infos

       ENTITY SASale
       CREATE BY \_SASeller AUTO FILL CID FIELDS ( SellerId Quota Confirmed )
       WITH sellers

       ENTITY SASale
       CREATE BY \_SASold AUTO FILL CID FIELDS ( MaterialId )
       WITH solds

       FAILED DATA(failed)
       MAPPED DATA(mapped)
       REPORTED DATA(reported).

 

Test

Nachdem wir nun auch Testdaten angelegt haben, schauen wir uns die Anwendung einmal im Detail an. Nach dem Aufruf und dem Laden der ersten Einträge, erhalten wir viele Felder und Filter im List Report.

 

Navigieren wir in die Details, dann sehen wir noch sehr viele UUIDS und noch keine richtige Struktur in den Details. Auf dem Bild siehst du einen Ausschnitt aus dem Bild, die weiteren Tabellen im unteren Bereich haben wir erst einmal weggelassen.

 

Vollständiges Beispiel

Das vollständige Coding findest du wie immer im GitHub Repository für unsere RAP Beispiele. Dafür haben wir ein neues Paket ZCL_SB_DEMO_RAP_SALES_FIELDS angelegt, wo das Beispiel und das Template liegen. Im Commit findest du alle generierten Artefakte vom heutigen Artikel.

 

Fazit

Die Generierung per Template erspart dir Arbeit bei der Anlage von RAP Objekten auf bereits existierenden Strukturen, Tabellen oder Entitäten. Dabei verwenden wir den Objekt Generator, um uns für die Schulung ein Template zu erstellen und im zweiten Schritt dann per Generator das RAP Objekt genieren zu lassen.


Enthaltene Themen:
RAPBTPTemplateGeneratorREX7
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.


RAP - Augmentation

Kategorie - ABAP

In diesem Artikel stellen wir unser Datenmodell der RAP Anwendung um und ändern die Form wie wir mit den Texten umgehen. Dabei verwenden wir Augmentation, um unser Datenmodell trotzdem vollständig zu halten.

03.02.2026

034: Recycling-Heroes - Object and RAP Generator (Document)

Kategorie - YouTube

In dieser Episode erstellen wir unsere neue Dokumenten-App mit Hilfe von Generatoren zur Erstellung des Datenmodells und anschließend zur Erstellung des RAP Objekts.

02.02.2026

CAP oder RAP - Eine Sicht aus dem Business

Kategorie - ABAP

Immer wieder wird über RAP, CAP oder Beides diskutiert, doch wie sieht es eigentlich mit dem Business aus? Welche Anforderungen und Punkte solltest du neben den Features eigentlich noch bedenken?

27.01.2026

RAP - Virtuelle Felder sortieren

Kategorie - ABAP

Haben wir virtuelle Felder in einer Entität im ABAP RESTful Application Programming Model implementiert, wie können wir dann eigentlich eine Sortierung verwenden? Schauen wir uns einmal den Prozess dazu an.

23.01.2026

RAP - Multi-Input Field

Kategorie - ABAP

Eine ganze Entität in einem Feld darstellen? Mit dem Multi-Input Field möglich. Heute schauen wir uns den Punkt in ABAP für die RAP Entwicklung an und schauen uns die Szenarien an.

20.01.2026