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

RAP - Custom Pattern

35

Wie funktioniert das Custom Pattern in der ABAP Entwicklung und für welche Szenarien kannst du es in der Entwicklung verwenden? Lass uns dazu ein Beispiel anschauen.

Werbung


In diesem Artikel schauen wir uns das Custom Pattern an, wie du es implementieren kannst und es 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 "Custom Pattern" wird so genannt, weil die Grundlage die Custom Entity ist, die uns aktuell die meiste Flexibilität bei der Umsetzung gibt, da wir ABAP Code zur Laufzeit ausführen können, um so die Datenermittlung zu machen, Schnittstellen aufzurufen oder einen Weg haben, altes Coding lauffähig zu halten. Zur Einleitung noch die Legende für das Modell.

 

Dazu die folgenden Merkmale zur Abgrenzung:

  • Aufbau des Datenmodells mit Custom Entities
  • Datenquelle meist über ABAP aufrufbar (API, Legacy Code, Funktionen oder lokale Daten)
  • Verhalten ist immer Unmanaged und kein Draft
  • Suchhilfen sind flexibel anbindbar (Lokal oder Remote)

 

 

Hinweis: Die Besonderheit bei der Custom Entity ist, dass wir auf dieser Entität nicht modellieren können und es daher bei der Interface Ebene bleibt. Weiterhin kannst du für eine Custom Entity keine Metadaten Erweiterung anlegen, daher müssen auch alle UI Annotationen in den gleichen View, was es nicht immer sehr einfach lesbar macht.

 

Beispiel

Um etwas tiefer in das Thema einzutauchen, schauen wir uns einmal ein Beispiel zu dem Thema an. Dabei werden wir eine Standard API konsumieren, um Informationen über unsere Software Komponenten aus dem Testsystem zu bekommen. In diesem Artikel werden wir uns auf die Anbindung der Schnittstelle, den Konsum der Daten und die Ausgabe in einer Fiori Elements Anwendung konzentrieren. In späteren Artikeln werden wir die Anwendung erweitern.

 

Schnittstelle

In diesem Kapitel provisionieren wir die Standardschnittstelle und lesen die ersten Daten aus dem System.

 

API

Damit wir die Software Komponenten aus dem Testsystem lesen können, verwenden wir die Standard API "Manage Git Repository" (SAP_COM_0510). Den Link zur API findest du unten in den weiterführenden Informationen. Dazu benötigen wir im ersten Schritt eine Verbindung zu unserem Testsystem und ein konfiguriertes Communication Arrangement auf dem System.

Schritte auf dem Testsystem:

  • Communication Arrangement für SAP_COM_0510
  • Communication System als Inbound Only
  • Communication User für den Zugriff auf das System

Schritte auf dem Entwicklungssystem:

  • Einrichtung Destination Service
  • Einrichtung Communication System für die Verbindung

 

Ob du den Destination Service verwendest oder über ein Communication System gehst, bleibt dir und der Strategie deines Unternehmens überlassen. In diesem Fall verwenden wir zur einfachen Anbindung den Destination Service im System.

 

Anbindung 

Um nun Daten aus der API lesen zu können, müssen wir die Struktur und die Definition im System bekannt machen. Dazu legen wir ein Consumption Model an. Bei MANAGE_GIT_REPOSITORY handelt es sich um ein Service Binding, welches uns eine OData v2 Web API zur Verfügung stellt. Wir können uns daher bei dem Endpunkt die Metadaten des Services laden, um daraus unser Consumption Model zu generieren.

 

Wie du die Einrichtung des Consumption Models machst, findest du in diesem Artikel zu Version v2 des Modells.

 

Daten

Nun erstellen wir die Klasse ZCL_BS_DEMO_CUSTOM_GIT, die wir in diesem Abschnitt beschreiben. Du wirst sie in GitHub nicht finden, da gewisse Bestandteile nicht veröffentlicht werden sollen. Damit wir nun die Daten lesen können, verwenden wir unsere wiederverwendbare Komponente. In der Methode GET_SWC_CONFIGURATION erzeugen wir uns eine Konfiguration, um den Provider zu instanziieren.

result = VALUE zif_bs_demo_service_prov=>configuration(
    cloud_destination = cloud_destination
    consumption_model = consumption_model_git
    service_root      = `/sap/opu/odata/sap/MANAGE_GIT_REPOSITORY`
    protocol          = zif_bs_demo_service_prov=>protocol-odata_v2 ).

 

Die Cloud Destination hatten wir zuvor im Destination Service angelegt, das Consumption Model ist der Name des angelegten Consumption Models aus dem Schritt zuvor. Dazu benötigen wir noch den relativen Pfad zum Service und das Protokoll für die Abfrage. Im nächsten Schritt können wir die Abfrage machen, dazu erzeugen wir mit der Konfiguration den Provider und übergeben die Einstellungen.

DATA(provider) = zcl_bs_demo_service_prov_fact=>create_service_provider( get_swc_configuration( ) ).

TRY.
    provider->read_odata_by_request( EXPORTING setting       = setting
                                     CHANGING  business_data = business_data
                                               count         = count ).
  CATCH cx_root.
    CLEAR business_data.
ENDTRY.

 

Über die Methode READ_ODATA_BY_REQUEST lesen wir die Daten und übergeben das Ergebnis an den Aufrufer. In den folgenden Abschnitten schauen wir uns noch die Aufrufstelle genauer an.

 

App

In diesem Kapitel legen wir die Grundstruktur der App an, um die Daten zu lesen und in der Anwendung zur Anzeige zu bringen.

 

Custom Entity

Im ersten Schritt definieren wir unseren Core Data Service als Custom Entity im System. Dazu schränken wir die Felder ein, die wir später in der Anzeige erhalten wollen:

  • Name der Software Komponente
  • Beschreibung
  • Typ
  • Verfügbar auf dem System
  • Aktiver Branch

 

Die Informationen zu den Feldern findest du in der generierten Klasse des Consumption Models, dort findest du den Namen, Typen und Länge zu dem Feld, wenn du die Custom Entity anlegen möchtest. Weiterhin hinterlegen wir auch schon die Query Klasse, über die wir gleich die Daten einlesen werden.

@EndUserText.label: 'Software Component'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_BS_DCP_SWC_QUERY'
define custom entity ZBS_R_DCPSoftwareComponent
{
  key sc_name       : abap.char(18);
      descr         : abap.char(60);
      sc_type_descr : abap.char(40);
      avail_on_inst : abap_boolean;
      active_branch : abap.char(40);
}

 

Hinweis: Sind die Namen der Felder gleich zu den Namen der Schnittstelle, erspart uns das später weitere Schritte bei den Filtern und Übergaben.

 

Query

Im nächsten Schritt müssen wir die Query Klasse implementieren, um die Daten dann zur Laufzeit zu ermitteln. Dazu legen wir die Klasse ZCL_BS_DCP_SWC_QUERY und implementieren das Interface IF_RAP_QUERY_PROVIDER. Für die Ermittlung der Daten legen wir noch eine eigene Methode an in der wir dann unsere Hilfsklasse aufrufen, um die Daten zu lesen. Wir benötigen auch einen lokalen Typen, um die Daten zurückzugeben.

TYPES software_components TYPE STANDARD TABLE OF ZBS_R_DCPSoftwareComponent WITH EMPTY KEY.

METHODS get_remote_data
  IMPORTING !request      TYPE REF TO if_rap_query_request
  EXPORTING business_data TYPE software_components
            !count        TYPE int8.

 

Wir übergeben die Entität die wir lesen wollen und das REQUEST Objekt um alle Parameter an den OData Service weiterzugeben. Im Request befinden sich auch Einstellungen, wie selektierte Felder, Sortierung und die Filter aus der Fiori Anwendung.

METHOD get_remote_data.
  NEW zcl_bs_demo_custom_git( )->get_software_component(
    EXPORTING setting       = VALUE #( entity_name = 'REPOSITORIES'
                                       request     = request )
    IMPORTING business_data = DATA(remote_data)
              count         = count ).

  business_data = CORRESPONDING #( remote_data ).
ENDMETHOD.

 

Das Ergebnis mappen wir dann vom Typen der Schnittstelle auf unsere Custom Entity und geben die Daten zurück in die SELECT Methode. Dort übergeben wir das Ergebnis noch an den RESPONSE der Methode (jeweils Daten und Count).

get_remote_data( EXPORTING request       = io_request
                 IMPORTING business_data = DATA(software_components)
                           count         = DATA(count) ).

IF io_request->is_data_requested( ).
  io_response->set_data( software_components ).
ENDIF.

IF io_request->is_total_numb_of_rec_requested( ).
  io_response->set_total_number_of_records( count ).
ENDIF.

 

Annotationen

Damit unsere Fiori Elements Anwendung auch noch ein paar mehr Informationen zeigt, definieren wir die UI Annotationen in der Custom Entity. Je nach Anzahl der Felder und Anzahl zusätzlicher UI Annotationen kann die Übersichtlichkeit etwas leiden.

@EndUserText.label: 'Software Component'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_BS_DCP_SWC_QUERY'
@UI.headerInfo: { typeName: 'Software Component',
                  typeNamePlural: 'Software Components',
                  title.value: 'sc_name',
                  description.value: 'descr' }
define custom entity ZBS_R_DCPSoftwareComponent
{
      @EndUserText.label: 'SWC'
      @UI.facet: [ { id: 'idRepositoryFields',
                     label: 'Technical Details',
                     position: 10,
                     type: #IDENTIFICATION_REFERENCE,
                     targetQualifier: 'REPO' } ]
      @UI.lineItem: [ { position: 20 } ]
      @UI.selectionField: [ { position: 20 } ]
  key sc_name       : abap.char(18);

      @EndUserText.label: 'Description'
      @UI.identification: [ { position: 20, qualifier: 'REPO' } ]
      @UI.lineItem: [ { position: 30 } ]
      descr         : abap.char(60);

      @EndUserText.label: 'Type'
      @UI.lineItem: [ { position: 40 } ]
      sc_type_descr : abap.char(40);

      @EndUserText.label: 'Available'
      @UI.lineItem: [ { position: 50 } ]
      @UI.selectionField: [ { position: 50 } ]      
      avail_on_inst : abap_boolean;

      @EndUserText.label: 'Branch'
      @UI.identification: [ { position: 30, qualifier: 'REPO' } ]
      @UI.lineItem: [ { position: 60 } ]
      active_branch : abap.char(40);
}

 

Dabei definieren wir einen Header für die Objektseite und zeigen alle Felder in der Liste an. Zusätzlich definieren wir noch einen Filter auf der Verfügbarkeit und auf der Software Komponente an sich.

 

Service

Zum Abschluss erzeugen wir noch direkt auf der Custom Entity eine Service Definition und ein Service Binding für unsere Anwendung. Zum Abschluss veröffentlichen wir den Service per "Publish" und können im nächsten Schritt unsere kleine Anwendung testen.

 

Test

Nachdem wir die Implementierung nun fertiggestellt haben, können wir die Anwendung erst einmal testen. Dazu prüfen wir den Aufruf der Daten und die Filter in der Anwendung.

 

Daten laden

Im ersten Schritt wollen wir einfach Daten sehen und rufen direkt über "Go" die Datenselektion auf. Unsere Logik wird durchlaufen und wir bekommen alle Software Komponenten des Zielsystems angezeigt.

 

Einige der Software Komponenten sind zum Beispiel auf dem Zielsystem nicht verfügbar, das bedeutet, dass noch kein Clone stattgefunden hat und wir die SWC aus dem globalen Verzeichnis geliefert bekommen. Grundsätzlich könnten wir auch nicht verfügbare Komponenten über einen zusätzlichen Filter direkt ausblenden lassen.

 

Daten filtern

Die Filter, die wir im oberen Bereich festlegen, werden über den REQUEST an unsere SELECT Methode weitergegeben. Über unsere generische Logik werden sie direkt an den OData Aufruf gegeben und wir erhalten nur die Daten, die zu dem Filter passen. Funktioniert mit den verschiedenen Einschränkungen und Möglichkeiten der Fiori Elements Floorplans.

 

Daten sortieren

Definieren wir auf der Spalte eine Sortierung, dann wird diese ebenfalls über die generische Implementierung abgebildet. In diesem Fall haben wir nach der SWC absteigend sortiert.

 

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_CUSTOM. Wie bereits oben beschrieben, wirst du das Consumption Model und die Aufrufimplementierung dort nicht finden.

 

Zusammenfassung

Das Custom Pattern gibt dir die Möglichkeit eine Anwendung zu erstellen, die nicht unbedingt auf Daten des aktuellen Systems basiert oder als Datenquelle eine Datenbank hat. In unserem Szenario haben wir mit wenigen Objekten unsere Anwendung zur Verfügung gestellt. Allerdings haben wir auch kein weiteres Verhalten oder zusätzliche Daten implementiert.

 

Dieses Anwendungsdesign kann gut verwendet werden, um zum Beispiel Legacy Code in ein RAP Objekt zu migrieren. Auch setzt SAP diese Art der Entwicklung ein, um Wrapper und Nachfolger zur Verfügung zu stellen, die im Bauch dann meist einen Standard BAPI verwenden und nicht direkt auf den fachlichen Tabellen basieren. 

Gewisse Einschränkungen, wie die fehlende Modellierung oder keine eigene Metadaten Erweiterung, machen die Entwicklung nicht ganz so übersichtlich, wie zum Beispiel das Classic Pattern. Dank der wiederverwendbaren Komponenten ist die volle Funktionalität der Datenbeschaffung mit wenigen Zeilen Code möglich und kann in verschiedenen Implementierungen wiederverwendet werden.

 

Fazit

In diesem Artikel haben wir die Grundlage für das Custom Pattern geschaffen und uns die verschiedenen Szenarien für die Nutzung angeschaut. Im nächsten Artikel werden wir das Modell dann um zusätzliche Daten und Verhalten erweitern.

 

Weitere Informationen:

SAP Help - Manage Git Repository


Enthaltene Themen:
RAPBTPPatternCustom
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 - Tree View (Löschverhalten)

Kategorie - ABAP

In diesem Artikel schauen wir uns das Verhalten beim Löschen von Knoten im Tree View mit RAP an. Dabei gibt es einige interessante Punkte zu beachten.

15.04.2025

RAP - Tree View

Kategorie - ABAP

Du möchtest eine Hierarchie in RAP ganz einfach darstellen? Wie das in ABAP Cloud funktioniert, erfährst du in diesem Artikel.

08.04.2025

RAP - Classic Pattern

Kategorie - ABAP

In diesem Artikel schauen wir uns das Classic Pattern an und gehen auf die Anwendungsfälle der Implementierung in ABAP Cloud ein.

25.03.2025

RAP - Popup Defaultwerte

Kategorie - ABAP

Wie kannst du im Popup einer Aktion in RAP dem User Defaultwerte zur Verfügung stellen? In diesem Artikel erweitern wir unsere Anwendung.

21.01.2025

RAP - Popup Pflichtfelder

Kategorie - ABAP

Wie kannst du eigentlich Pflichtfelder für ein Popup in RAP definieren? In diesem Artikel werden wir etwas genauer auf die Details eingehen.

14.01.2025