RAP - Aktion (Teil 2)
Es folgt der zweite Teil für die Aktionen in RAP, bei dem wir noch auf weitere Details in der Verwendung eingehen wollen und um Sonderfälle aufzuzeigen.
Inhaltsverzeichnis
Im ersten Teil dieses Artikels sind wir vor allem auf die Einbindung von Aktionen in einfacher und statischer Form eingegangen. In diesem Artikel wollen wir etwas auf Selbstreferenzen und Factory Actions eingehen und wozu man sie nutzt.
Rückgabewerte
Im letzten Artikel definierten wir zwei Aktionen ohne Rückgabeparameter, sodass der Aufrufer bei Ausführung keine entsprechende Information bekommt, sondern sich zum Beispiel den Datensatz noch einmal nachlesen müsste, um die aktuellen Daten zu erhalten. Diese Arbeit kannst du übernehmen, in dem du einen Rückgabeparameter definierst und diesen nach Aufruf der Methode befüllst.
Dazu erweitern wir die Definition der Aktion in der Verhaltensdefinition. Nach dem Keyword "result" kommt die Kardinalität, wie du sie auch aus den Core Data Services kennst. Im Anschluss kommt der Rückgabetyp, den die Methode zurückgibt.
action fillEmptyStreets result [1] $self;
Die Referenz $self bezieht sich auf die Entität, in der die Aktion definiert wurde. Es wird also eine Instanz vom Datentyp "ZBS_I_RAPPartner" zurückgegeben. Die Implementierung muss nun noch entsprechend neu generiert oder um den RESULT Zusatz erweitert werden.
METHODS fillemptystreets FOR MODIFY
IMPORTING keys FOR ACTION partner~fillemptystreets RESULT result.
Ohne die Implementierung des Rückgabewerts, also keiner weiteren Änderung, geschieht eine Navigation bei Ausführung der Aktion. Allerdings ist das angezeigte Bild dann auch leer, da keine Instanz zurückgegeben wurde. Mit dem neuen Zusatz erfolgt also immer eine Navigation zur entsprechenden Entität und das Übersichtsbild wird verlassen.
Wir fügen nun am Ende der Methode das neue Coding ein, um das "result" zu befüllen und die Daten der Entität zurückzugeben.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner
FIELDS ( Street )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
LOOP AT lt_partner_data INTO DATA(ls_partner) WHERE Street IS INITIAL.
ls_partner-Street = 'EMPTY'.
MODIFY ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner
UPDATE FIELDS ( Street )
WITH VALUE #( ( %tky = ls_partner-%tky Street = ls_partner-Street %control-Street = if_abap_behv=>mk-on ) ).
INSERT VALUE #( %tky = ls_partner-%tky %param = ls_partner ) INTO TABLE result.
ENDLOOP.
Innerhalb des Loops befüllen wir nun das Ergebnis mit dem Schlüssel (%TKY) und den neuen Daten im Feld Parameter. Dabei könnten die Daten per READ auch einfach von der Datenbank nachgelesen werden, um sich zu gehen, dass die aktuellen Daten zur Verfügung gestellt werden. Werden die Daten korrekt übergeben, dann wird nicht mehr ins Detailbild gesprungen.
Hinweis: Rückgabewerte können folgende Typen haben: Strukturen, Entitäten, Abstrakte Entitäten.
Factory Action
Wie der Name es beschreibt generiert so eine Methode eine Instanz der aktuellen Entität, dass kann unter anderem beim Kopieren passieren. Die Definition weicht deshalb etwas ab. Eingeleitet wird mit dem Schlüsselwort "factory". Am Ende wird eine Kardinalität mitgegeben, das "result" kann allerdings entfallen, da immer $self herangezogen wird.
factory action copyLine [1];
Über den Quick Fix (STRG + 1) kannst du die Methode in der Verhaltensimplementierung generieren lassen und musst nur noch die Implementierung entwickeln. Das neue Coding ist nun etwas umfangreicher:
DATA:
lt_creation TYPE TABLE FOR CREATE ZBS_I_RAPPartner.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
SELECT FROM zbs_dmo_partner
FIELDS MAX( partner )
INTO @DATA(ld_number).
LOOP AT lt_partner_data INTO DATA(ls_partner).
ld_number += 1.
ls_partner-PartnerNumber = ld_number.
ls_partner-PartnerName &&= | copy|.
INSERT VALUE #( %cid = keys[ sy-tabix ]-%cid ) INTO TABLE lt_creation REFERENCE INTO DATA(lr_create).
lr_create->* = CORRESPONDING #( ls_partner ).
lr_create->%control-PartnerNumber = if_abap_behv=>mk-on.
lr_create->%control-PartnerName = if_abap_behv=>mk-on.
lr_create->%control-Street = if_abap_behv=>mk-on.
lr_create->%control-City = if_abap_behv=>mk-on.
lr_create->%control-Country = if_abap_behv=>mk-on.
lr_create->%control-PaymentCurrency = if_abap_behv=>mk-on.
ENDLOOP.
MODIFY ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner CREATE FROM lt_creation
FAILED DATA(ls_failed)
MAPPED DATA(ls_mapped)
REPORTED DATA(ls_reported).
mapped-partner = ls_mapped-partner.
Im ersten Schritt lesen wir den markierten Satz und erzeugen dafür eine Tabelle von anzulegenden Datensätzen. Zuvor ermitteln wir die höchste Partnernummer und vergeben die Nummer plus 1. Da Partnernummer der Schlüssel ist, muss die Nummer immer eindeutig sein. Im Anschluss werden die neuen Datensätze per MODIFY auf die Datenbank übernommen. Der Commit darf innerhalb der Verarbeitung nicht gesetzt werden und wird vom Framework durchgeführt. Am Ende übergeben wir noch die Daten aus der MAPPED Struktur an den Parameter MAPPED der Struktur.
Hinweis: Wichtig ist vor allem, dass die übergebene CID auch zurückgegeben wird, sonst erhält man ein leeres Detailbild.
EML
Aktionen lassen sich auch per EML auslösen, dazu kann das MODIFY Statement verwendet werden. Entsprechend musst du nur die auszulösende Aktion angeben und den Schlüssel des Datensatz mitgeben. Wichtig bei der Rückgabe ist vor allem RESULT, da hier die Rückgabe enthalten ist.
MODIFY ENTITIES OF ZBS_I_RAPPartner
ENTITY Partner EXECUTE fillEmptyStreets
FROM VALUE #( ( PartnerNumber = '1000000007' ) )
RESULT DATA(lt_new_partner)
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported).
COMMIT ENTITIES.
Wichtig ist in diesem Fall auch der COMMIT, damit die Aktion ausgelöst wird. Mapped, Failed und Reported sind nicht unbedingt benötigt, vervollständigen aber das Ergebnis. Das Ergebnis sieht nun wie folgt aus:
Hier noch einmal die vollständige Klasse zu diesem Beispiel:
CLASS zcl_bs_demo_action_eml DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bs_demo_action_eml IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
MODIFY ENTITIES OF ZBS_I_RAPPartner
ENTITY Partner EXECUTE fillEmptyStreets
FROM VALUE #( ( PartnerNumber = '1000000007' ) )
RESULT DATA(lt_new_partner)
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported).
COMMIT ENTITIES.
IF line_exists( lt_new_partner[ 1 ] ).
out->write( lt_new_partner[ 1 ]-PartnerNumber ).
out->write( lt_new_partner[ 1 ]-%param ).
ELSE.
out->write( `Not worked` ).
ENDIF.
ENDMETHOD.
ENDCLASS.
Fazit
Im Bereich der Aktionen kann man viele unterschiedliche Ansätze verfolgen und je nachdem wie eine Aktion funktionieren soll, muss man auch die unterschiedlichen Dinge berücksichtigen. Der Rückgabewert der Aktion kann optional auch wichtig sein, muss aber nicht immer befüllt sein.