Actions sind das Herzstück der Geschäftslogik in RAP. Doch welchen Action-Typ wählt man wann? Dieser Artikel vergleicht alle Verarbeitungsoptionen und zeigt anhand von Flugbuchungs-Beispielen, wie jeder Typ implementiert wird.
Übersicht der Action-Typen
RAP bietet verschiedene Action-Typen für unterschiedliche Anwendungsfälle:
| Action-Typ | Bindung | Zweck | Beispiel |
|---|---|---|---|
| Instance Action | An Entität gebunden | Operation auf ausgewählter Instanz | Buchung stornieren |
| Static Action | Keine Instanz-Bindung | Massenoperationen, Neuanlage | Alle offenen Buchungen freigeben |
| Factory Action | An Entität gebunden | Neue Instanz aus bestehender erstellen | Buchung kopieren |
| Action mit Parameter | Instance oder Static | Benutzereingaben vor Ausführung | Stornierung mit Grund |
| Action mit Ergebnis | Instance oder Static | Rückgabe von Daten | Preis neu berechnen |
Instance Action: Operation auf einer Entität
Instance Actions arbeiten auf einer oder mehreren ausgewählten Instanzen. Der häufigste Action-Typ.
Behavior Definition
managed implementation in class zbp_i_flightbooking unique;strict ( 2 );
define behavior for ZI_FlightBooking alias FlightBookingpersistent table zflight_booklock masterauthorization master ( instance ){ create; update; delete;
// Instance Action ohne Parameter action confirmBooking result [1] $self;
// Instance Action mit Status-Rückgabe action cancelBooking result [1] $self;
// Instance Action ohne Ergebnis action markAsNoShow;}Implementation
CLASS lhc_flightbooking DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS confirmBooking FOR MODIFY IMPORTING keys FOR ACTION FlightBooking~confirmBooking RESULT result.
METHODS cancelBooking FOR MODIFY IMPORTING keys FOR ACTION FlightBooking~cancelBooking RESULT result.
METHODS markAsNoShow FOR MODIFY IMPORTING keys FOR ACTION FlightBooking~markAsNoShow.ENDCLASS.
CLASS lhc_flightbooking IMPLEMENTATION. METHOD confirmBooking. " Buchungen bestätigen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky booking_status = 'C' " Confirmed ) ).
" Aktualisierte Daten lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
" Ergebnis zurückgeben result = VALUE #( FOR booking IN bookings ( %tky = booking-%tky %param = booking ) ).
" Success-Nachricht APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = |{ lines( bookings ) } Buchung(en) bestätigt| ) ) TO reported-flightbooking. ENDMETHOD.
METHOD cancelBooking. " Zuerst prüfen ob Stornierung erlaubt READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking FIELDS ( booking_status flight_date ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). " Nur offene oder bestätigte Buchungen stornierbar IF booking-booking_status <> 'O' AND booking-booking_status <> 'C'. APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = |Buchung im Status { booking-booking_status } kann nicht storniert werden| ) ) TO reported-flightbooking. APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking. CONTINUE. ENDIF.
" Stornierung durchführen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status cancellation_date ) WITH VALUE #( ( %tky = booking-%tky booking_status = 'X' " Cancelled cancellation_date = cl_abap_context_info=>get_system_date( ) ) ). ENDLOOP.
" Ergebnis lesen und zurückgeben READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(updated_bookings).
result = VALUE #( FOR bk IN updated_bookings ( %tky = bk-%tky %param = bk ) ). ENDMETHOD.
METHOD markAsNoShow. " Einfache Action ohne Ergebnis-Rückgabe MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status no_show_date ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky booking_status = 'N' " No-Show no_show_date = cl_abap_context_info=>get_system_date( ) ) ).
" Nur Nachricht, kein result APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = 'Als No-Show markiert' ) ) TO reported-flightbooking. ENDMETHOD.ENDCLASS.Result-Kardinalität
| Syntax | Bedeutung | Verwendung |
|---|---|---|
result [1] $self | Genau eine Instanz der gleichen Entität | Standard für Statusänderungen |
result [0..1] $self | Optional eine Instanz | Wenn Ergebnis nicht garantiert |
result [0..*] $self | Beliebig viele Instanzen | Massenoperationen |
result [1] EntityName | Eine andere Entität | Navigation zu verwandter Entität |
| (kein result) | Keine Rückgabe | Fire-and-forget Operationen |
Static Action: Massenoperationen und Neuanlage
Static Actions sind nicht an eine Instanz gebunden. Sie werden typischerweise für globale Operationen verwendet.
Behavior Definition
define behavior for ZI_FlightBooking alias FlightBooking{ // Static Action für Massenoperation static action releaseAllPending;
// Static Action mit Ergebnis static action createQuickBooking result [1] $self;
// Static Action mit Feature Control static action ( features: global ) sendDailyReport;
// Für Global Feature Control static features;}Implementation
CLASS lhc_flightbooking IMPLEMENTATION. METHOD releaseAllPending. " Alle Buchungen mit Status 'Pending' finden SELECT * FROM zflight_book WHERE booking_status = 'P' INTO TABLE @DATA(pending_bookings).
IF pending_bookings IS INITIAL. APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-information text = 'Keine ausstehenden Buchungen gefunden' ) ) TO reported-flightbooking. RETURN. ENDIF.
" Alle auf 'Confirmed' setzen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( FOR booking IN pending_bookings ( booking_id = booking-booking_id booking_status = 'C' " Confirmed ) ).
APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = |{ lines( pending_bookings ) } Buchungen freigegeben| ) ) TO reported-flightbooking. ENDMETHOD.
METHOD createQuickBooking. " Schnellbuchung mit Standardwerten erstellen DATA(today) = cl_abap_context_info=>get_system_date( ). DATA(user) = cl_abap_context_info=>get_user_technical_name( ).
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking CREATE FIELDS ( flight_date customer_id flight_id booking_status flight_price currency_code created_by created_at ) WITH VALUE #( ( %cid = 'QUICK_BOOKING' flight_date = today + 14 " In 2 Wochen customer_id = get_default_customer( user ) flight_id = get_next_available_flight( today + 14 ) booking_status = 'P' " Pending flight_price = 299 currency_code = 'EUR' created_by = user created_at = cl_abap_context_info=>get_system_time( ) ) ) MAPPED DATA(mapped).
" Erstellte Buchung lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH VALUE #( ( %tky = mapped-flightbooking[ 1 ]-%tky ) ) RESULT DATA(created_bookings).
" Ergebnis mit %cid_ref zurückgeben result = VALUE #( ( %cid_ref = 'QUICK_BOOKING' %param = created_bookings[ 1 ] ) ).
APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = 'Schnellbuchung erstellt' ) ) TO reported-flightbooking. ENDMETHOD.
METHOD get_global_features. " Prüfen ob Benutzer Berechtigung für Report hat DATA(has_report_auth) = check_report_authorization( ).
result = VALUE #( %action-sendDailyReport = COND #( WHEN has_report_auth = abap_true THEN if_abap_behv=>fc-o-enabled ELSE if_abap_behv=>fc-o-disabled ) ). ENDMETHOD.ENDCLASS.Factory Action: Neue Instanz aus bestehender
Factory Actions erstellen eine neue Instanz basierend auf einer existierenden. Ideal für Kopier- und Vorlagen-Szenarien.
Behavior Definition
define behavior for ZI_FlightBooking alias FlightBooking{ // Factory Action erstellt Kopie factory action copyBooking [1];
// Factory Action mit Parametern factory action rebookToDate parameter ZA_RebookParams [1];}Implementation
CLASS lhc_flightbooking IMPLEMENTATION. METHOD copyBooking. " Originalbuchungen lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
DATA: lt_mapped TYPE RESPONSE FOR MAPPED EARLY zi_flightbooking.
LOOP AT bookings INTO DATA(booking). DATA(lv_cid) = |COPY_{ sy-tabix }|.
" Kopie mit neuem Status erstellen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking CREATE FIELDS ( flight_date customer_id flight_id flight_price currency_code booking_status created_by created_at ) WITH VALUE #( ( %cid = lv_cid flight_date = booking-flight_date customer_id = booking-customer_id flight_id = booking-flight_id flight_price = booking-flight_price currency_code = booking-currency_code booking_status = 'P' " Neue Buchung als Pending created_by = cl_abap_context_info=>get_user_technical_name( ) created_at = cl_abap_context_info=>get_system_time( ) ) ) MAPPED DATA(mapped_single).
" mapped aggregieren APPEND VALUE #( %cid_ref = keys[ sy-tabix ]-%cid_ref %key = mapped_single-flightbooking[ 1 ]-%key ) TO mapped-flightbooking. ENDLOOP.
APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = |{ lines( bookings ) } Buchung(en) kopiert| ) ) TO reported-flightbooking. ENDMETHOD.
METHOD rebookToDate. " Originalbuchungen lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT keys ASSIGNING FIELD-SYMBOL(<key>). READ TABLE bookings INTO DATA(booking) WITH KEY booking_id = <key>-booking_id.
" Neues Datum aus Parameter DATA(new_date) = <key>-%param-NewFlightDate.
" Validierung IF new_date < cl_abap_context_info=>get_system_date( ). APPEND VALUE #( %tky = <key>-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Neues Datum muss in der Zukunft liegen' ) ) TO reported-flightbooking. APPEND VALUE #( %tky = <key>-%tky ) TO failed-flightbooking. CONTINUE. ENDIF.
" Neue Buchung mit neuem Datum erstellen DATA(lv_cid) = |REBOOK_{ sy-tabix }|.
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking CREATE FIELDS ( flight_date customer_id flight_id flight_price currency_code booking_status original_booking_id ) WITH VALUE #( ( %cid = lv_cid flight_date = new_date customer_id = booking-customer_id flight_id = booking-flight_id flight_price = booking-flight_price currency_code = booking-currency_code booking_status = 'P' " Pending original_booking_id = booking-booking_id " Referenz zur Originalbuchung ) ) MAPPED DATA(mapped_single).
" Originalbuchung auf 'Rebooked' setzen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( ( %tky = <key>-%tky booking_status = 'R' " Rebooked ) ).
APPEND VALUE #( %cid_ref = <key>-%cid_ref %key = mapped_single-flightbooking[ 1 ]-%key ) TO mapped-flightbooking. ENDLOOP. ENDMETHOD.ENDCLASS.Action mit Ergebnis-Parameter
Actions können strukturierte Ergebnisse zurückgeben, die über $self hinausgehen.
Abstract Entity für Ergebnis
@EndUserText.label: 'Preisberechnung Ergebnis'define abstract entity ZA_PriceCalculation{ BookingId : abap.numc(10); NetPrice : abap.curr(15,2); TaxAmount : abap.curr(15,2); TotalPrice : abap.curr(15,2); Currency : abap.cuky; DiscountPct : abap.dec(5,2); DiscountText : abap.string(100);}Behavior Definition
define behavior for ZI_FlightBooking alias FlightBooking{ // Action mit eigenem Ergebnis-Typ action recalculatePrice result [1] ZA_PriceCalculation;
// Action die andere Entität zurückgibt action createInvoice result [1] ZI_Invoice;}Implementation
METHOD recalculatePrice. " Buchungsdaten lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking FIELDS ( booking_id flight_price currency_code customer_id ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). " Kundenrabatt ermitteln DATA(discount_pct) = get_customer_discount( booking-customer_id ). DATA(net_price) = booking-flight_price * ( 1 - discount_pct / 100 ). DATA(tax_amount) = net_price * '0.19'. DATA(total_price) = net_price + tax_amount.
" Preis in Buchung aktualisieren MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( flight_price ) WITH VALUE #( ( %tky = booking-%tky flight_price = total_price ) ).
" Ergebnis-Struktur befüllen APPEND VALUE #( %tky = booking-%tky %param = VALUE za_pricecalculation( BookingId = booking-booking_id NetPrice = net_price TaxAmount = tax_amount TotalPrice = total_price Currency = booking-currency_code DiscountPct = discount_pct DiscountText = COND #( WHEN discount_pct > 0 THEN |Stammkundenrabatt: { discount_pct }%| ELSE 'Kein Rabatt' ) ) ) TO result. ENDLOOP.ENDMETHOD.Fehlerbehandlung in Actions
Robuste Actions müssen Fehler korrekt behandeln und dem Benutzer melden.
Pattern: Validierung vor Ausführung
METHOD processBooking. DATA: lt_failed TYPE TABLE FOR FAILED EARLY zi_flightbooking, lt_reported TYPE TABLE FOR REPORTED EARLY zi_flightbooking.
" Buchungen lesen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). " === VALIDIERUNGSPHASE ===
" Fehler 1: Status prüfen IF booking-booking_status = 'X'. APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Stornierte Buchungen können nicht verarbeitet werden' ) ) TO lt_reported. APPEND VALUE #( %tky = booking-%tky ) TO lt_failed. CONTINUE. ENDIF.
" Fehler 2: Datum prüfen IF booking-flight_date < cl_abap_context_info=>get_system_date( ). APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Flugdatum liegt in der Vergangenheit' ) %element-flight_date = if_abap_behv=>mk-on ) TO lt_reported. APPEND VALUE #( %tky = booking-%tky ) TO lt_failed. CONTINUE. ENDIF.
" Warnung: Hoher Preis IF booking-flight_price > 2000. APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-warning text = |Preis über 2.000 { booking-currency_code }| ) %element-flight_price = if_abap_behv=>mk-on ) TO lt_reported. " KEIN failed-Eintrag bei Warning! ENDIF.
" === AUSFÜHRUNGSPHASE === TRY. " Geschäftslogik ausführen MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status processed_at ) WITH VALUE #( ( %tky = booking-%tky booking_status = 'D' " Done processed_at = cl_abap_context_info=>get_system_time( ) ) ).
CATCH cx_root INTO DATA(lx_error). " Unerwarteter Fehler APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = |Systemfehler: { lx_error->get_text( ) }| ) ) TO lt_reported. APPEND VALUE #( %tky = booking-%tky ) TO lt_failed. ENDTRY. ENDLOOP.
" Fehler und Meldungen übergeben failed-flightbooking = lt_failed. reported-flightbooking = lt_reported.
" Ergebnis für erfolgreiche Buchungen READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(updated_bookings).
result = VALUE #( FOR bk IN updated_bookings WHERE ( booking_status = 'D' ) ( %tky = bk-%tky %param = bk ) ).ENDMETHOD.Pattern: Partielle Erfolge
METHOD batchProcess. DATA: lv_success_count TYPE i, lv_error_count TYPE i.
READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). IF can_process( booking ). " Verarbeiten MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( ( %tky = booking-%tky booking_status = 'D' ) ).
lv_success_count = lv_success_count + 1. ELSE. " Fehler sammeln, aber weitermachen APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = |Buchung { booking-booking_id }: Verarbeitung nicht möglich| ) ) TO reported-flightbooking. APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking.
lv_error_count = lv_error_count + 1. ENDIF. ENDLOOP.
" Zusammenfassende Nachricht IF lv_success_count > 0 AND lv_error_count > 0. APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-warning text = |{ lv_success_count } verarbeitet, { lv_error_count } fehlgeschlagen| ) ) TO reported-flightbooking. ELSEIF lv_success_count > 0. APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success text = |{ lv_success_count } Buchungen verarbeitet| ) ) TO reported-flightbooking. ENDIF.ENDMETHOD.Entscheidungsmatrix: Welche Action wann?
| Anforderung | Action-Typ | Beispiel |
|---|---|---|
| Statusänderung einer Buchung | Instance Action | confirmBooking, cancelBooking |
| Alle offenen Buchungen freigeben | Static Action | releaseAllPending |
| Buchung kopieren | Factory Action | copyBooking |
| Stornierung mit Grund | Instance Action + Parameter | cancelWithReason |
| Neue Buchung ohne Vorlage | Static Action + Result | createQuickBooking |
| Umbuchung auf neues Datum | Factory Action + Parameter | rebookToDate |
| Preis neu berechnen und anzeigen | Instance Action + Result Entity | recalculatePrice |
| Rechnung aus Buchung erstellen | Instance Action + andere Entity | createInvoice |
Wann Instance vs. Static?
┌─────────────────────────────────────────────────────────────────┐│ Braucht die Action ││ Instanz-Kontext? ││ │ ││ ┌───────────┴───────────┐ ││ │ │ ││ ▼ ▼ ││ [ JA ] [ NEIN ] ││ │ │ ││ ┌──────────┴──────────┐ │ ││ │ │ ▼ ││ ▼ ▼ STATIC ACTION ││ Erstellt neue Ändert ││ Instanz? bestehende? ││ │ │ ││ ▼ ▼ ││ FACTORY INSTANCE ││ ACTION ACTION │└─────────────────────────────────────────────────────────────────┘Wann mit oder ohne Parameter?
| Szenario | Mit Parameter | Ohne Parameter |
|---|---|---|
| Benutzereingabe erforderlich | ✓ Popup-Dialog | |
| Bestätigung ohne Details | ✓ Direkte Ausführung | |
| Optionale Zusatzinfos | ✓ Parameter mit Defaults | |
| Aktion mit Auswahlmöglichkeiten | ✓ Parameter mit Value Help |
Wann Result verwenden?
| Szenario | Result-Typ |
|---|---|
| UI soll aktualisiert werden | result [1] $self |
| Fire-and-Forget | Kein Result |
| Berechnungsergebnis anzeigen | result [1] ZA_ResultEntity |
| Massenoperation mit Einzelergebnissen | result [0..*] $self |
| Verwandte Entität erstellt | result [1] OtherEntity |
Best Practices
1. Konsistente Namenskonvention
" ✅ Verben für Actionsaction confirmBooking ...action cancelBooking ...action recalculatePrice ...
" ❌ Substantive vermeidenaction confirmation ... " Unklar was passiertaction cancellation ...2. Result immer angeben für UI-Refresh
" ✅ UI wird nach Action aktualisiertaction confirmBooking result [1] $self;
" ❌ UI bleibt auf altem Standaction confirmBooking; " Ohne result3. Fehler früh erkennen
METHOD myAction. " ✅ Validierung ZUERST, vor jeder Änderung READ ENTITIES ... LOOP AT ... IF NOT valid( ). " Fehler melden und CONTINUE CONTINUE. ENDIF. ENDLOOP.
" Erst nach Validierung: Änderungen durchführen MODIFY ENTITIES ...ENDMETHOD.4. IN LOCAL MODE verwenden
" ✅ Umgeht Berechtigungsprüfung innerhalb der ActionREAD ENTITIES OF zi_flightbooking IN LOCAL MODE ...MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ...5. Feature Control kombinieren
" Behavior Definitionaction ( features: instance ) cancelBooking result [1] $self;determination setFeatures on modify { field booking_status; }
" Implementation: cancelBooking nur für offene Buchungen aktivierenZusammenfassung
| Action-Typ | Wann verwenden | Keys vorhanden | Erstellt Instanz |
|---|---|---|---|
| Instance | Operation auf Selektion | ✓ | Nein |
| Static | Globale Operation | Nein | Optional |
| Factory | Kopieren, Vorlagen | ✓ | Ja |
Die richtige Wahl des Action-Typs macht den Unterschied zwischen einer intuitiven und einer verwirrenden Benutzeroberfläche. Verwenden Sie Instance Actions für Einzeloperationen, Static Actions für globale Aktionen und Factory Actions für das Erstellen neuer Instanzen aus bestehenden.
Weiterführende Artikel: RAP Actions und Functions für Grundlagen, Popup-Aktionen für Actions mit Dialog, RAP Nachrichten für Fehlerbehandlung und Feature Control für dynamische Aktivierung.