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

RAP - Custom Entity mit Aktion

307

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.

Werbung


Die Frage des heutigen Artikels kam aus der Community von Abdullah ATAN. Dabei gehen wir auf die Details er Implementierung ein und wie das Beispiel genau funktioniert.

 

Einleitung

Die Frage wurde auch in der SAP Community gestellt, wie eigentlich eine Action in einer Custom Entity implementiert werden kann. Dabei wurde auch normales EML verwendet, wobei allerdings einiges zu beachten ist, damit es sauber funktioniert. Deshalb haben wir dazu ein kleines Beispiel erstellt, welches du einfach übernehmen und ausprobieren kannst.

 

Umsetzung

In diesem Kapitel schauen wir in die Umsetzung schauen uns verschiedene Details der Implementierung an, die in diesem Fall wichtig sind. Wie du allgemein eine Custom Entity aufbaust, findest du in diesem Artikel beschrieben.

 

Custom Entity

Starten wir im ersten Schritt mit einer Custom Entity, die unsere Struktur und das UI abbilden wird. Neben der Definition des Typen, müssen wir noch die Queryklasse angeben, die die Daten liefern soll.

@EndUserText.label: 'Custom Entity with Action'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_BS_DEMO_CUSTOM_ACTION_QRY'
define root custom entity ZBS_R_CusActEntityTP
{
  key my_key      : abap.char(15);
      description : abap.char(60);
      icon        : abap.sstring(250);
}

 

Query

Im nächsten Schritt implementieren wir die Query, die uns hart codierte Daten zur Verfügung stellen. Damit wollen wir im ersten Schritt eine API simulieren, die uns vielleicht per HTTP die Daten zur Verfügung stellt. Die Menge der Daten müssen wir dann noch über die Filter und die Sortierung entsprechend für die Rückgabe vorbereiten.

CLASS zcl_bs_demo_custom_action_qry DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_rap_query_provider.

    TYPES result_type TYPE STANDARD TABLE OF ZBS_R_CusActEntityTP WITH EMPTY KEY.

    METHODS get_dummy_data
      RETURNING VALUE(result) TYPE result_type.
ENDCLASS.


CLASS zcl_bs_demo_custom_action_qry IMPLEMENTATION.
  METHOD if_rap_query_provider~select.
    DATA result TYPE STANDARD TABLE OF ZBS_R_CusActEntityTP.
    DATA count  TYPE int8.

    result = get_dummy_data( ).

    NEW zcl_bs_demo_adjust_data( )->adjust_via_request( EXPORTING io_request = io_request
                                                        CHANGING  ct_data    = result
                                                                  cd_count   = count ).

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

    IF io_request->is_data_requested( ).
      io_response->set_data( result ).
    ENDIF.
  ENDMETHOD.


  METHOD get_dummy_data.
    RETURN VALUE #( ( my_key = 'TEST' description = 'First One' )
                    ( my_key = 'NOTHING' description = 'Second One' )
                    ( my_key = 'MORE' description = 'Third One' ) ).
  ENDMETHOD.
ENDCLASS.

 

Verhalten

Im nächsten Schritt definieren wir auf der Custom Entity ein Verhalten, um später die Implementierung in RAP zu machen. Wir möchten später den Update verwenden, um den Status in einer Datenbank zu aktualisieren, diesen aber nur INTERNAL, innerhalb des RAP Objekts. Wir definieren uns eine normale Aktion, die uns ebenfalls ein Ergebnis (sich selbst) zurückgibt. Damit wollen wir die Aktualisierung des Datensatzes erreichen. Die statische Aktion verwenden wir für das Zurücksetzen aller Status.

unmanaged implementation in class zbp_bs_demo_custom_action unique;
strict ( 2 );

define behavior for ZBS_R_CusActEntityTP alias CustomAction
lock master
authorization master ( instance )
{
  internal update;

  field ( readonly ) my_key;

  action myCustomAction result [1] $self;
  static action resetAllIcons;
}

 

UI

Damit die Liste und Felder angezeigt werden, benötigen wir noch UI Annotationen. Diese müssen wir direkt in der Custom Entity definieren. Dabei definieren wir auch die zwei Aktionen im UI. Für das Feld ICON definieren wir noch, dass dieses als Bild dargestellt wird.

@EndUserText.label: 'Custom Entity with Action'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_BS_DEMO_CUSTOM_ACTION_QRY'
define root custom entity ZBS_R_CusActEntityTP
{
      @UI.facet   : [{
        position  : 10,
        label     : 'General',
        type      : #IDENTIFICATION_REFERENCE
      }]

      @UI.lineItem: [{ position: 10 }, 
        { type: #FOR_ACTION, dataAction: 'myCustomAction', label: 'Custom Action' },
        { type: #FOR_ACTION, dataAction: 'resetAllIcons', label: 'Reset' } ]
      @UI.selectionField: [{ position: 10 }]
      @UI.identification: [{ position: 10 }]
      @EndUserText.label: 'Identifier'
  key my_key      : abap.char(15);

      @UI.lineItem: [{ position: 20, iconUrl: 'icon' }]
      @UI.identification: [{ position: 20 }]
      @EndUserText.label: 'Description'
      description : abap.char(60);

      @UI.lineItem: [{ position: 30 }]
      @EndUserText.label: 'Icon'
      @Semantics.imageUrl: true
      icon        : abap.sstring(250);
}

 

Implementierung

Kommen wir nun zur eigentlichen Implementierung der Aktion in der Verhaltensimplementierung. Die Custom Action würden wir nun wie folgt implementieren.

METHOD myCustomAction.
  READ ENTITIES OF ZBS_R_CusActEntityTP IN LOCAL MODE
       ENTITY CustomAction
       FROM CORRESPONDING #( keys )
       RESULT DATA(found_data).

  LOOP AT found_data INTO DATA(found).
    MODIFY ENTITIES OF ZBS_R_CusActEntityTP IN LOCAL MODE
           ENTITY CustomAction
           UPDATE FROM VALUE #( ( my_key               = found-my_key
                                  description          = found-description
                                  %control-description = if_abap_behv=>mk-on ) ).

    INSERT VALUE #( my_key = found-my_key
                    %param = found ) INTO TABLE result.
  ENDLOOP.
ENDMETHOD.

 

Wir lesen die selektierten Daten, führen dann einen Update durch und geben die Daten zurück, damit das UI den Datensatz aktualisieren kann. Damit allerdings auch das EML funktioniert, müssen wir die beiden Methoden implementieren. In der READ Methode lassen wir uns die Daten geben und müssen den Schlüssel dann filtern, um die korrekten Sätze zu lesen. Die Implementierung ist hier sehr einfach gehalten.

METHOD read.
  DATA(all) = NEW zcl_bs_demo_custom_action_qry( )->get_dummy_data( ).

  LOOP AT keys INTO DATA(key).
    INSERT CORRESPONDING #( all[ my_key = key-my_key ] ) INTO TABLE result.
  ENDLOOP.
ENDMETHOD.

 

In der Update Methode befüllen wir eigentlich nur den Puffer, da die eigentliche Aktion erst beim Speichern passieren soll.

METHOD update.
  INSERT LINES OF entities INTO TABLE lcl_data_buffer=>updates.
ENDMETHOD.

 

In der SAVE Methode führen wir dann das eigentliche Handling der Speicherung durch. In diesem Fall befüllen wir eine Tabelle, die zum Schlüssel den aktuellen Status enthält. Damit können wir Zusatzdaten zu unseren "API" Daten sichern und in der Queryklasse dazu lesen.

METHOD save.
  LOOP AT lcl_data_buffer=>updates INTO DATA(update).
    SELECT SINGLE FROM zbs_dmo_cstat
      FIELDS status
      WHERE my_key = @update-my_key
      INTO @DATA(found_status).

    IF sy-subrc <> 0.
      INSERT zbs_dmo_cstat FROM @( VALUE #( my_key = update-my_key
                                            status = 1 ) ).
    ELSE.
      UPDATE zbs_dmo_cstat FROM @( VALUE #( my_key = update-my_key
                                            status = found_status + 1 ) ).
    ENDIF.
  ENDLOOP.
ENDMETHOD.

 

Anreicherung

Im letzten Schritt reichern wir in der Queryklasse die Daten des Ergebnisses an. Dazu lesen wir die Statustabelle und leiten das entsprechende Icon ab, dass wir ausgeben wollen.

LOOP AT result REFERENCE INTO DATA(extend).
  SELECT SINGLE FROM zbs_dmo_cstat
    FIELDS status
    WHERE my_key = @extend->my_key
    INTO @DATA(found_status).

  IF sy-subrc <> 0.
    extend->icon = icons-none.
    CONTINUE.
  ENDIF.

  CASE found_status.
    WHEN 1.
      extend->icon = icons-one.
    WHEN 2.
      extend->icon = icons-two.
    WHEN 3.
      extend->icon = icons-three.
    WHEN OTHERS.
      extend->icon = icons-four.
  ENDCASE.
ENDLOOP.

 

Ergebnis

Hier ein Beispiel wie nun die Anwendung funktioniert und sich verhält. Dabei verändern wir den Status der einzelnen Zeilen und machen zum Abschluss einen Reset des Status über eine weitere Action.

 

Vollständiges Beispiel

Das vollständige Beispiel aus diesem Artikel findest du bei uns im GitHub Repository im Paket ZBS_DEMO_RAP_CUSTOM_ACTION. Im Commit kannst du noch einmal die verschiedenen Änderungen anschauen, die ins Repo gekommen sind.

 

Fazit

Bei der Implementierung einer Aktion in einer Custom Entity kannst du dich auf das RAP Framework verlassen, musst allerdings auch das Handling selbst übernehmen. Bei einem Unmanaged Szenario allerdings auch eindeutig klar. Da von Custom Entities aktuell kein Draft unterstützt wird, reicht in vielen Fällen ein OData v2 Service, wenn du auch die Standardaktionen verwenden willst.


Enthaltene Themen:
RAPBTPCustom EntityAction
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 - 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 - API Pattern

Kategorie - ABAP

In diesem Artikel schauen wir uns das API-Pattern für RAP an und wie du es flexibel in der ABAP Entwicklung einsetzen kannst, um Schnittstellen zur Verfügung zu stellen.

20.06.2025

RAP - Mehrere Filter und Einstellungen

Kategorie - ABAP

Wie sieht es eigentlich aus, wenn wir in RAP mehrere Filter und Felder als Standard setzen wollen und dazu noch eine standardmäßige Sortierung benötigen?

16.05.2025