Business Events in RAP ermöglichen event-driven Architecture: Statt direkter Methodenaufrufe kommunizieren Komponenten über Events. Das entkoppelt Systeme, ermöglicht asynchrone Verarbeitung und macht Architekturen skalierbarer und wartbarer.
Das Problem: Tight Coupling
Ohne Events (Tight Coupling)
" ❌ Direkte Abhängigkeit: Travel → Email → LoggingMETHOD approve_travel. " 1. Status ändern MODIFY ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = ls_travel-%tky Status = 'A' ) ).
" 2. Email senden (direkte Abhängigkeit!) TRY. cl_email_sender=>send( recipient = ls_travel-customer_email subject = 'Travel approved' ). CATCH cx_email_error. " Was tun bei Fehler? ENDTRY.
" 3. Loggen (direkte Abhängigkeit!) cl_logger=>log( |Travel { ls_travel-TravelId } approved| ).
" 4. Analytics updaten (direkte Abhängigkeit!) zcl_analytics=>track_approval( ls_travel-TravelId ).
" 5. External System benachrichtigen (direkte Abhängigkeit!) zcl_external_api=>notify_approval( ls_travel ).ENDMETHOD.Probleme:
- 🔴 Tight Coupling: Approval-Logik kennt alle Consumers
- 🔴 Synchron: Alle Schritte blockieren Hauptprozess
- 🔴 Nicht erweiterbar: Neuer Consumer = Code ändern
- 🔴 Fehleranfällig: Ein fehlgeschlagener Consumer bricht alles ab
- 🔴 Langsam: Email + API + Logging = 2-3 Sekunden
Mit Events (Loose Coupling)
" ✅ Event-driven: Travel → Event → Consumers (entkoppelt)METHOD approve_travel. " 1. Status ändern MODIFY ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = ls_travel-%tky Status = 'A' ) ).
" 2. Event auslösen (Fire & Forget) RAISE ENTITY EVENT zi_travel~TravelApproved FROM VALUE #( ( %key-TravelId = ls_travel-TravelId %param-ApprovedBy = sy-uname %param-ApprovedAt = sy-datum ) ).
" Fertig! Consumers reagieren asynchronENDMETHOD.Vorteile:
- ✅ Loose Coupling: Approval-Logik kennt keine Consumers
- ✅ Asynchron: Consumers verarbeiten parallel
- ✅ Erweiterbar: Neue Consumers ohne Code-Änderung
- ✅ Resilient: Consumer-Fehler beeinflussen Hauptprozess nicht
- ✅ Schnell: Hauptprozess läuft sofort weiter (< 100ms)
Event Anatomy
┌─────────────────────────────────────────────────────┐│ Event Publisher ││ (RAP Business Object) ││ ││ METHOD approve_travel. ││ RAISE ENTITY EVENT zi_travel~TravelApproved ... ││ ENDMETHOD. │└────────────────┬────────────────────────────────────┘ │ │ Event: TravelApproved │ Payload: { TravelId, ApprovedBy, ApprovedAt } │ ▼┌─────────────────────────────────────────────────────┐│ Event Infrastructure ││ (RAP Framework / Event Mesh) │└────────┬────────────────────────────────┬──────────┘ │ │ ▼ ▼┌────────────────────┐ ┌────────────────────────┐│ Consumer 1 │ │ Consumer 2 ││ (Email) │ │ (Analytics) ││ │ │ ││ on_event( ). │ │ on_event( ). ││ send_email( ) │ │ track_approval( ) │└────────────────────┘ └────────────────────────┘ │ ▼┌────────────────────┐│ Consumer 3 ││ (External API) ││ ││ on_event( ). ││ notify_system( ) │└────────────────────┘Event Definition in BDEF
Einfaches Event
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance ){ create; update; delete;
// Event Definition event TravelApproved;
// Action die Event auslöst action approve result [1] $self;}Event mit Parametern
define behavior for ZI_Travel alias Travel{ // Event mit Parameter-Struktur event TravelApproved parameter ZA_TravelApprovedParam;
action approve result [1] $self;}Parameter-Struktur (Abstract Entity):
@EndUserText.label: 'Travel Approved Event Parameters'define abstract entity ZA_TravelApprovedParam{ TravelId : /dmo/travel_id; ApprovedBy : syuname; ApprovedAt : sydatum; ApprovalNote : abap.string(255);}Event mit Standard-Parameter
define behavior for ZI_Travel alias Travel{ // Event mit vordefiniertem %param event TravelApproved parameter ZA_TravelApprovedParam;
// Oder: Nur Key-Felder (kein expliziter Parameter) event TravelCancelled;}Event Raising (Publisher)
Event in Action auslösen
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS approve FOR MODIFY IMPORTING keys FOR ACTION Travel~approve RESULT result.ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD approve. " 1. Daten lesen READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_travel) FAILED failed REPORTED reported.
" 2. Status ändern MODIFY ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( Status ApprovedBy ApprovedAt ) WITH VALUE #( FOR travel IN lt_travel ( %tky = travel-%tky Status = 'A' ApprovedBy = cl_abap_context_info=>get_user_name( ) ApprovedAt = cl_abap_context_info=>get_system_date( ) ) ) FAILED failed REPORTED reported.
" 3. Event auslösen RAISE ENTITY EVENT zi_travel~TravelApproved FROM VALUE #( FOR travel IN lt_travel ( %key-TravelId = travel-TravelId %param-ApprovedBy = cl_abap_context_info=>get_user_name( ) %param-ApprovedAt = cl_abap_context_info=>get_system_date( ) %param-ApprovalNote = 'Approved via action' ) ).
" 4. Ergebnis zurückgeben READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys ) RESULT result. ENDMETHOD.
ENDCLASS.Event in Validation/Determination
METHOD validateDates. READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel FIELDS ( BeginDate EndDate ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_travel).
LOOP AT lt_travel INTO DATA(ls_travel). IF ls_travel-EndDate < ls_travel-BeginDate. " Validation-Fehler APPEND VALUE #( %tky = ls_travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = ls_travel-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Invalid date range' ) ) TO reported-travel.
" Event: ValidationFailed auslösen RAISE ENTITY EVENT zi_travel~ValidationFailed FROM VALUE #( ( %key-TravelId = ls_travel-TravelId %param-ErrorType = 'DATE_RANGE' %param-ErrorMessage = 'End date before begin date' ) ). ENDIF. ENDLOOP.ENDMETHOD.Mehrere Events
define behavior for ZI_Travel alias Travel{ // Verschiedene Events für verschiedene Szenarien event TravelCreated; event TravelApproved; event TravelRejected parameter ZA_RejectionParam; event TravelCancelled; event TravelCompleted;}METHOD approve. " ... RAISE ENTITY EVENT zi_travel~TravelApproved FROM ...ENDMETHOD.
METHOD reject. " ... RAISE ENTITY EVENT zi_travel~TravelRejected FROM VALUE #( ( %key-TravelId = ls_travel-TravelId %param-RejectionReason = ls_key-%param-Reason ) ).ENDMETHOD.
METHOD cancel. " ... RAISE ENTITY EVENT zi_travel~TravelCancelled FROM ...ENDMETHOD.Event Consumption (Subscriber)
Event Handler implementieren
CLASS zcl_travel_event_handler DEFINITION PUBLIC CREATE PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_travel_event_handler IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. " Event-Key auswerten CASE event_key.
WHEN 'TravelApproved'. handle_travel_approved( event_data ).
WHEN 'TravelRejected'. handle_travel_rejected( event_data ).
WHEN 'TravelCancelled'. handle_travel_cancelled( event_data ).
ENDCASE. ENDMETHOD.
" Private Methoden für Event-Handling METHODS: handle_travel_approved IMPORTING it_event_data TYPE STANDARD TABLE,
handle_travel_rejected IMPORTING it_event_data TYPE STANDARD TABLE,
handle_travel_cancelled IMPORTING it_event_data TYPE STANDARD TABLE.
ENDCLASS.Event Handler registrieren
Service Definition:
@EndUserText.label: 'Travel Event Handler'define service ZUI_TRAVEL_EVENTS { expose ZI_Travel as Travel;
// Event Handler aktivieren expose zcl_travel_event_handler as TravelEventHandler;}Oder: Programmatische Registrierung:
" In Initialisierungsklasse oder beim SystemstartDATA(lo_event_handler) = NEW zcl_travel_event_handler( ).
" Handler registrierencl_rap_event_handler=>register( iv_event_name = 'TravelApproved' io_handler = lo_event_handler).Event-Daten verarbeiten
METHOD handle_travel_approved. " Event-Daten sind eine Tabelle (kann mehrere Events sein) LOOP AT it_event_data INTO DATA(ls_event).
" %key und %param extrahieren DATA(lv_travel_id) = ls_event-%key-TravelId. DATA(lv_approved_by) = ls_event-%param-ApprovedBy. DATA(lv_approved_at) = ls_event-%param-ApprovedAt.
" 1. Email senden send_approval_email( iv_travel_id = lv_travel_id iv_approved_by = lv_approved_by ).
" 2. Analytics tracken track_approval_analytics( iv_travel_id = lv_travel_id iv_approved_at = lv_approved_at ).
" 3. Externe API benachrichtigen notify_external_system( iv_travel_id = lv_travel_id ).
" 4. Loggen cl_bali_log=>create( )->add_item( cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_information text = |Travel { lv_travel_id } approved by { lv_approved_by }| ) )->save( ).
ENDLOOP.ENDMETHOD.Fehlerbehandlung im Consumer
METHOD handle_travel_approved. LOOP AT it_event_data INTO DATA(ls_event).
" Email-Versand mit Fehlerbehandlung TRY. send_approval_email( ls_event-%key-TravelId ). CATCH cx_email_error INTO DATA(lx_email). " Fehler loggen, aber Event-Verarbeitung NICHT abbrechen cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_email ) )->save( ).
" Optional: Retry-Logik add_to_retry_queue( iv_event_type = 'TravelApproved' iv_travel_id = ls_event-%key-TravelId ). ENDTRY.
" API-Call mit Fehlerbehandlung TRY. notify_external_system( ls_event-%key-TravelId ). CATCH cx_http_error INTO DATA(lx_http). " Fehler loggen cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_http ) )->save( ). ENDTRY.
ENDLOOP.ENDMETHOD.Praktische Use Cases
Use Case 1: Multi-Channel Benachrichtigung
" Event: TravelApproved" → Consumer 1: Email" → Consumer 2: SMS" → Consumer 3: Push Notification" → Consumer 4: Slack
CLASS zcl_notification_handler DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_notification_handler IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. CHECK event_key = 'TravelApproved'.
LOOP AT event_data INTO DATA(ls_event). DATA(lv_travel_id) = ls_event-%key-TravelId.
" Kunde-Präferenzen laden SELECT SINGLE * FROM zcustomer_prefs WHERE travel_id = @lv_travel_id INTO @DATA(ls_prefs).
" Multi-Channel Benachrichtigung (parallel) IF ls_prefs-notify_email = abap_true. send_email( lv_travel_id ). ENDIF.
IF ls_prefs-notify_sms = abap_true. send_sms( lv_travel_id ). ENDIF.
IF ls_prefs-notify_push = abap_true. send_push_notification( lv_travel_id ). ENDIF.
IF ls_prefs-notify_slack = abap_true. send_slack_message( lv_travel_id ). ENDIF. ENDLOOP. ENDMETHOD.
ENDCLASS.Use Case 2: Audit Trail
CLASS zcl_audit_trail_handler DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_audit_trail_handler IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. " Alle Events auditen LOOP AT event_data INTO DATA(ls_event).
" Audit-Eintrag erstellen INSERT INTO zaudit_log VALUES ( audit_id = cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ) entity_type = 'TRAVEL' entity_key = ls_event-%key-TravelId event_type = event_key event_date = sy-datum event_time = sy-uzeit user_name = sy-uname event_payload = /ui2/cl_json=>serialize( ls_event ) ).
ENDLOOP.
COMMIT WORK. ENDMETHOD.
ENDCLASS.Use Case 3: Workflow Trigger
CLASS zcl_workflow_trigger_handler DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_workflow_trigger_handler IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. CHECK event_key = 'TravelApproved'.
LOOP AT event_data INTO DATA(ls_event). DATA(lv_travel_id) = ls_event-%key-TravelId.
" Travel-Details laden SELECT SINGLE * FROM zi_travel WHERE TravelId = @lv_travel_id INTO @DATA(ls_travel).
" Workflow triggern für teure Reisen IF ls_travel-TotalAmount > 10000.
" SAP Build Process Automation Workflow starten DATA(lo_workflow) = cl_spa_workflow=>get_instance( ).
lo_workflow->start_workflow( workflow_id = 'HighValueTravelApproval' context = VALUE #( travel_id = lv_travel_id amount = ls_travel-TotalAmount approved_by = ls_event-%param-ApprovedBy ) ).
ENDIF. ENDLOOP. ENDMETHOD.
ENDCLASS.Use Case 4: Cache Invalidation
CLASS zcl_cache_handler DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_cache_handler IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. " Bei allen Travel-Events: Cache invalidieren CASE event_key. WHEN 'TravelApproved' OR 'TravelRejected' OR 'TravelCancelled'.
LOOP AT event_data INTO DATA(ls_event). " Cache für diese Travel löschen cl_cache_manager=>invalidate( cache_area = 'TRAVEL' key = ls_event-%key-TravelId ).
" Optional: Related Caches auch löschen " (z.B. Customer-Travel-List) SELECT SINGLE CustomerId FROM zi_travel WHERE TravelId = @ls_event-%key-TravelId INTO @DATA(lv_customer_id).
cl_cache_manager=>invalidate( cache_area = 'CUSTOMER_TRAVELS' key = lv_customer_id ). ENDLOOP.
ENDCASE. ENDMETHOD.
ENDCLASS.Integration mit SAP Event Mesh
Event Mesh Setup
Was ist SAP Event Mesh?
- Cloud-Service für Enterprise Event Bus
- Entkoppelt Publisher und Consumer über Message Queue
- Unterstützt Pub/Sub-Pattern
- Multi-Tenant, skalierbar, hochverfügbar
Event nach Event Mesh publishen
CLASS zcl_event_mesh_publisher DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_rap_entity_event_subscriber.ENDCLASS.
CLASS zcl_event_mesh_publisher IMPLEMENTATION.
METHOD if_rap_entity_event_subscriber~on_business_event. " RAP Event nach Event Mesh weiterleiten
LOOP AT event_data INTO DATA(ls_event).
" Event als JSON serialisieren DATA(lv_json_payload) = /ui2/cl_json=>serialize( data = ls_event compress = abap_false ).
" HTTP Client für Event Mesh DATA(lo_http) = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_cloud_destination( i_name = 'EVENT_MESH' i_authn_mode = if_a4c_cp_service=>service_specific ) ).
" POST Request DATA(lo_request) = lo_http->get_http_request( ).
lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
lo_request->set_header_field( i_name = 'x-qos' " Quality of Service i_value = '1' " At least once ).
lo_request->set_text( lv_json_payload ).
" Event Topic DATA(lv_topic) = |sap/s4/travel/{ event_key }|.
TRY. DATA(lo_response) = lo_http->execute( i_method = if_web_http_client=>post i_uri = |/messagingrest/v1/topics/{ lv_topic }/messages| ).
IF lo_response->get_status( )-code = 204. " Erfolgreich published cl_bali_log=>create( )->add_item( cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_information text = |Event { event_key } published to Event Mesh| ) )->save( ). ENDIF.
CATCH cx_web_http_client_error INTO DATA(lx_http). " Fehler loggen cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_http ) )->save( ). ENDTRY.
ENDLOOP. ENDMETHOD.
ENDCLASS.Event von Event Mesh consumieren
" Webhook Endpoint für Event Mesh CallbacksCLASS zcl_event_mesh_consumer DEFINITION PUBLIC. PUBLIC SECTION. INTERFACES if_http_service_extension.ENDCLASS.
CLASS zcl_event_mesh_consumer IMPLEMENTATION.
METHOD if_http_service_extension~handle_request. " Event Mesh sendet Events via HTTP POST
" JSON Payload extrahieren DATA(lv_payload) = request->get_text( ).
" Deserialisieren DATA ls_event TYPE zi_travel_event. /ui2/cl_json=>deserialize( EXPORTING json = lv_payload CHANGING data = ls_event ).
" Event verarbeiten CASE ls_event-event_type. WHEN 'TravelApproved'. " Lokale Verarbeitung process_travel_approved( ls_event ).
WHEN 'TravelRejected'. process_travel_rejected( ls_event ). ENDCASE.
" Response response->set_status( i_code = 200 i_reason = 'OK' ).
ENDMETHOD.
ENDCLASS.Testing von Events
Event Raising testen
CLASS ltc_travel_events DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION. DATA mo_environment TYPE REF TO if_cds_test_environment.
METHODS: setup, teardown, test_approve_raises_event FOR TESTING.ENDCLASS.
CLASS ltc_travel_events IMPLEMENTATION.
METHOD setup. mo_environment = cl_cds_test_environment=>create( i_for_entity = 'ZI_Travel' ).
" Testdaten mo_environment->insert_test_data( i_data = VALUE zi_travel( ( TravelId = '00000001' Status = 'O' CustomerId = '000042' ) ) ). ENDMETHOD.
METHOD test_approve_raises_event. " Arrange: Event Spy registrieren DATA(lo_event_spy) = NEW lcl_event_spy( ). " (In echten Tests: Framework-spezifischer Spy)
" Act: Action ausführen (sollte Event raisen) MODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE approve FROM VALUE #( ( TravelId = '00000001' ) ) FAILED DATA(failed).
COMMIT ENTITIES.
" Assert: Event wurde ausgelöst " (Framework-abhängig - hier konzeptuell) cl_abap_unit_assert=>assert_equals( exp = 1 act = lo_event_spy->get_event_count( 'TravelApproved' ) msg = 'Event TravelApproved should be raised' ).
" Assert: Event-Parameter korrekt DATA(ls_event) = lo_event_spy->get_event( 'TravelApproved' ). cl_abap_unit_assert=>assert_equals( exp = '00000001' act = ls_event-%key-TravelId ). ENDMETHOD.
METHOD teardown. ROLLBACK ENTITIES. mo_environment->destroy( ). ENDMETHOD.
ENDCLASS.Event Handler testen
CLASS ltc_event_handler DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION. DATA mo_cut TYPE REF TO zcl_travel_event_handler.
METHODS: setup, test_handle_approved_event FOR TESTING.ENDCLASS.
CLASS ltc_event_handler IMPLEMENTATION.
METHOD setup. mo_cut = NEW zcl_travel_event_handler( ). ENDMETHOD.
METHOD test_handle_approved_event. " Arrange: Mock Event Data DATA(lt_event_data) = VALUE zi_travel_event_tab( ( %key-TravelId = '00000001' %param-ApprovedBy = 'TEST_USER' %param-ApprovedAt = '20250101' ) ).
" Act mo_cut->if_rap_entity_event_subscriber~on_business_event( event_key = 'TravelApproved' event_data = lt_event_data ).
" Assert: Prüfen dass Handler korrekt verarbeitet hat " (z.B. Email gesendet, Log-Eintrag erstellt) " → Hängt von Implementation ab ENDMETHOD.
ENDCLASS.Event Patterns
Pattern 1: Event Chaining
" Event 1 triggert Event 2 triggert Event 3
" Publisher 1METHOD create_travel. " ... RAISE ENTITY EVENT zi_travel~TravelCreated FROM ...ENDMETHOD.
" Consumer 1 = Publisher 2CLASS zcl_handler_1 IMPLEMENTATION. METHOD on_business_event. CHECK event_key = 'TravelCreated'.
" Validation durchführen validate_travel( event_data ).
" Nächstes Event RAISE ENTITY EVENT zi_travel~TravelValidated FROM ... ENDMETHOD.ENDCLASS.
" Consumer 2 = Publisher 3CLASS zcl_handler_2 IMPLEMENTATION. METHOD on_business_event. CHECK event_key = 'TravelValidated'.
" Approval-Prozess starten start_approval( event_data ).
" Nächstes Event RAISE ENTITY EVENT zi_travel~ApprovalStarted FROM ... ENDMETHOD.ENDCLASS.Pattern 2: Event Aggregation
" Mehrere Events zu einem Summary-Event aggregieren
CLASS zcl_event_aggregator IMPLEMENTATION. METHOD on_business_event. " Events sammeln CASE event_key. WHEN 'TravelApproved' OR 'TravelRejected' OR 'TravelCancelled'. " In-Memory Counter add_to_statistics( event_key ). ENDCASE.
" Jede Stunde: Summary-Event IF hour_passed( ). RAISE EVENT DailySummary FROM VALUE #( ( approvals = mv_approval_count rejections = mv_rejection_count cancellations = mv_cancellation_count ) ).
reset_statistics( ). ENDIF. ENDMETHOD.ENDCLASS.Pattern 3: Event Filtering
" Nur bestimmte Events weiterverarbeiten
CLASS zcl_high_value_handler IMPLEMENTATION. METHOD on_business_event. CHECK event_key = 'TravelCreated'.
LOOP AT event_data INTO DATA(ls_event). " Travel-Details laden SELECT SINGLE TotalAmount FROM zi_travel WHERE TravelId = @ls_event-%key-TravelId INTO @DATA(lv_amount).
" Nur High-Value Travels (> 10.000) CHECK lv_amount > 10000.
" Special Handling notify_manager( ls_event-%key-TravelId ). require_additional_approval( ls_event-%key-TravelId ). ENDLOOP. ENDMETHOD.ENDCLASS.Wichtige Hinweise / Best Practice
- Loose Coupling: Events entkoppeln Publisher und Consumer
- Asynchron: Events ermöglichen asynchrone Verarbeitung
- Fire & Forget: Publisher kümmert sich nicht um Consumer-Erfolg
- Idempotenz: Event Handler sollten idempotent sein (mehrfaches Verarbeiten = OK)
- Fehlerbehandlung: Consumer-Fehler dürfen Publisher nicht beeinflussen
- Event Naming: Vergangenheitsform (
TravelApproved, nichtApproveTravel) - Event Payload: Nur notwendige Daten (keine großen Objekte)
- Versionierung: Event-Struktur nie brechen (nur erweitern)
- Testing: Events explizit testen (Spy-Pattern)
- Monitoring: Event-Verarbeitung loggen und monitoren
- Retry-Logic: Fehlgeschlagene Events in Queue für Retry
- Event Mesh: Für System-übergreifende Events nutzen
- Documentation: Events und ihre Consumer dokumentieren
Weitere Ressourcen
- RAP Basics: /rap-basics/
- EML Guide: /eml-entity-manipulation-language/
- RAP Determinations/Validations: /rap-determinations-validations/
- ABAP Cloud: /abap-cloud-definition/