Les Business Events dans RAP permettent une architecture événementielle : au lieu d’appels de méthodes directs, les composants communiquent via des événements. Cela découple les systèmes, permet un traitement asynchrone et rend les architectures plus évolutives et maintenables.
Le problème : Couplage fort
Sans événements (Tight Coupling)
" ❌ Dépendance directe : Travel → Email → LoggingMETHOD approve_travel. " 1. Changer le statut MODIFY ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = ls_travel-%tky Status = 'A' ) ).
" 2. Envoyer un email (dépendance directe !) TRY. cl_email_sender=>send( recipient = ls_travel-customer_email subject = 'Travel approved" ). CATCH cx_email_error. " Que faire en cas d'erreur ? ENDTRY.
" 3. Journaliser (dépendance directe !) cl_logger=>log( |Travel { ls_travel-TravelId } approved| ).
" 4. Mettre à jour Analytics (dépendance directe !) zcl_analytics=>track_approval( ls_travel-TravelId ).
" 5. Notifier un système externe (dépendance directe !) zcl_external_api=>notify_approval( ls_travel ).ENDMETHOD.Problèmes :
- 🔴 Tight Coupling : La logique d’approbation connaît tous les Consumers
- 🔴 Synchrone : Toutes les étapes bloquent le processus principal
- 🔴 Non extensible : Nouveau Consumer = modification du code
- 🔴 Fragile : Un Consumer en échec interrompt tout
- 🔴 Lent : Email + API + Logging = 2-3 secondes
Avec événements (Loose Coupling)
" ✅ Événementiel : Travel → Event → Consumers (découplé)METHOD approve_travel. " 1. Changer le statut MODIFY ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = ls_travel-%tky Status = 'A' ) ).
" 2. Déclencher l'événement (Fire & Forget) RAISE ENTITY EVENT zi_travel~TravelApproved FROM VALUE #( ( %key-TravelId = ls_travel-TravelId %param-ApprovedBy = sy-uname %param-ApprovedAt = sy-datum ) ).
" Terminé ! Les Consumers réagissent de manière asynchroneENDMETHOD.Avantages :
- ✅ Loose Coupling : La logique d’approbation ne connaît pas les Consumers
- ✅ Asynchrone : Les Consumers traitent en parallèle
- ✅ Extensible : Nouveaux Consumers sans modification du code
- ✅ Résilient : Les erreurs des Consumers n’affectent pas le processus principal
- ✅ Rapide : Le processus principal continue immédiatement (< 100ms)
Anatomie d’un événement
┌─────────────────────────────────────────────────────┐│ 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( ) │└────────────────────┘Définition d’événement dans BDEF
Événement simple
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance ){ create; update; delete;
// Définition d'événement event TravelApproved;
// Action qui déclenche l'événement action approve result [1] $self;}Événement avec paramètres
define behavior for ZI_Travel alias Travel{ // Événement avec structure de paramètres event TravelApproved parameter ZA_TravelApprovedParam;
action approve result [1] $self;}Structure de paramètres (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);}Événement avec paramètre standard
define behavior for ZI_Travel alias Travel{ // Événement avec %param prédéfini event TravelApproved parameter ZA_TravelApprovedParam;
// Ou : Seulement les champs clés (pas de paramètre explicite) event TravelCancelled;}Déclenchement d’événements (Publisher)
Déclencher un événement dans une Action
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. Lire les données READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_travel) FAILED failed REPORTED reported.
" 2. Changer le statut 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. Déclencher l'événement 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. Retourner le résultat READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys ) RESULT result. ENDMETHOD.
ENDCLASS.Événement dans 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. " Erreur de validation 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: Déclencher ValidationFailed 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.Plusieurs événements
define behavior for ZI_Travel alias Travel{ // Différents événements pour différents scénarios 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.Consommation d’événements (Subscriber)
Implémenter Event Handler
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. " Évaluer l'event-key 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.
" Méthodes privées pour la gestion des événements 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.Enregistrer Event Handler
Service Definition :
@EndUserText.label: 'Travel Event Handler"define service ZUI_TRAVEL_EVENTS { expose ZI_Travel as Travel;
// Activer Event Handler expose zcl_travel_event_handler as TravelEventHandler;}Ou : Enregistrement programmatique :
" Dans la classe d'initialisation ou au démarrage du systèmeDATA(lo_event_handler) = NEW zcl_travel_event_handler( ).
" Enregistrer le handlercl_rap_event_handler=>register( iv_event_name = 'TravelApproved" io_handler = lo_event_handler).Traiter les données d’événement
METHOD handle_travel_approved. " Les données d'événement sont une table (peut contenir plusieurs événements) LOOP AT it_event_data INTO DATA(ls_event).
" Extraire %key et %param 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. Envoyer un email send_approval_email( iv_travel_id = lv_travel_id iv_approved_by = lv_approved_by ).
" 2. Suivre dans Analytics track_approval_analytics( iv_travel_id = lv_travel_id iv_approved_at = lv_approved_at ).
" 3. Notifier le système externe notify_external_system( iv_travel_id = lv_travel_id ).
" 4. Journaliser 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.Gestion des erreurs dans le Consumer
METHOD handle_travel_approved. LOOP AT it_event_data INTO DATA(ls_event).
" Envoi d'email avec gestion des erreurs TRY. send_approval_email( ls_event-%key-TravelId ). CATCH cx_email_error INTO DATA(lx_email). " Journaliser l'erreur, mais NE PAS interrompre le traitement de l'événement cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_email ) )->save( ).
" Optionnel : Logique de retry add_to_retry_queue( iv_event_type = 'TravelApproved" iv_travel_id = ls_event-%key-TravelId ). ENDTRY.
" Appel API avec gestion des erreurs TRY. notify_external_system( ls_event-%key-TravelId ). CATCH cx_http_error INTO DATA(lx_http). " Journaliser l'erreur cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_http ) )->save( ). ENDTRY.
ENDLOOP.ENDMETHOD.Cas d’usage pratiques
Cas d’usage 1 : Notification multi-canal
" 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.
" Charger les préférences client SELECT SINGLE * FROM zcustomer_prefs WHERE travel_id = @lv_travel_id INTO @DATA(ls_prefs).
" Notification multi-canal (parallèle) 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.Cas d’usage 2 : Piste d’audit
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. " Auditer tous les événements LOOP AT event_data INTO DATA(ls_event).
" Créer une entrée d'audit 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.Cas d’usage 3 : Déclencheur de workflow
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.
" Charger les détails du voyage SELECT SINGLE * FROM zi_travel WHERE TravelId = @lv_travel_id INTO @DATA(ls_travel).
" Déclencher le workflow pour les voyages coûteux IF ls_travel-TotalAmount > 10000.
" Démarrer le workflow SAP Build Process Automation 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.Cas d’usage 4 : Invalidation du cache
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. " Pour tous les événements Travel : invalider le cache CASE event_key. WHEN 'TravelApproved' OR 'TravelRejected' OR 'TravelCancelled'.
LOOP AT event_data INTO DATA(ls_event). " Supprimer le cache pour ce Travel cl_cache_manager=>invalidate( cache_area = 'TRAVEL" key = ls_event-%key-TravelId ).
" Optionnel : Supprimer aussi les caches liés " (par ex. 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.Intégration avec SAP Event Mesh
Configuration Event Mesh
Qu’est-ce que SAP Event Mesh ?
- Service cloud pour Enterprise Event Bus
- Découple Publisher et Consumer via Message Queue
- Supporte le pattern Pub/Sub
- Multi-tenant, évolutif, haute disponibilité
Publier vers Event Mesh
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. " Transférer l'événement RAP vers Event Mesh
LOOP AT event_data INTO DATA(ls_event).
" Sérialiser l'événement en JSON DATA(lv_json_payload) = /ui2/cl_json=>serialize( data = ls_event compress = abap_false ).
" Client HTTP pour 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 ) ).
" Requête POST 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 ).
" Topic de l'événement 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. " Publié avec succès 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). " Journaliser l'erreur cl_bali_log=>create( )->add_item( cl_bali_message_setter=>create_from_exception( lx_http ) )->save( ). ENDTRY.
ENDLOOP. ENDMETHOD.
ENDCLASS.Consommer depuis Event Mesh
" Endpoint Webhook pour les callbacks Event MeshCLASS 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 envoie des événements via HTTP POST
" Extraire le payload JSON DATA(lv_payload) = request->get_text( ).
" Désérialiser DATA ls_event TYPE zi_travel_event. /ui2/cl_json=>deserialize( EXPORTING json = lv_payload CHANGING data = ls_event ).
" Traiter l'événement CASE ls_event-event_type. WHEN 'TravelApproved'. " Traitement local process_travel_approved( ls_event ).
WHEN 'TravelRejected'. process_travel_rejected( ls_event ). ENDCASE.
" Réponse response->set_status( i_code = 200 i_reason = 'OK' ).
ENDMETHOD.
ENDCLASS.Tests d’événements
Tester le déclenchement d’événements
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" ).
" Données de test mo_environment->insert_test_data( i_data = VALUE zi_travel( ( TravelId = '00000001' Status = 'O' CustomerId = '000042' ) ) ). ENDMETHOD.
METHOD test_approve_raises_event. " Arrange: Enregistrer Event Spy DATA(lo_event_spy) = NEW lcl_event_spy( ). " (Dans les vrais tests : Spy spécifique au framework)
" Act: Exécuter l'action (devrait lever l'événement) MODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE approve FROM VALUE #( ( TravelId = '00000001' ) ) FAILED DATA(failed).
COMMIT ENTITIES.
" Assert: L'événement a été déclenché " (Dépendant du framework - ici conceptuel) cl_abap_unit_assert=>assert_equals( exp = 1 act = lo_event_spy->get_event_count( 'TravelApproved' ) msg = 'Event TravelApproved should be raised" ).
" Assert: Paramètres de l'événement corrects 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.Tester Event Handler
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: Vérifier que le Handler a traité correctement " (par ex. email envoyé, entrée de log créée) " → Dépend de l'implémentation ENDMETHOD.
ENDCLASS.Patterns d’événements
Pattern 1 : Chaînage d’événements
" Event 1 déclenche Event 2 déclenche 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'.
" Effectuer la validation validate_travel( event_data ).
" Événement suivant 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'.
" Démarrer le processus d'approbation start_approval( event_data ).
" Événement suivant RAISE ENTITY EVENT zi_travel~ApprovalStarted FROM ... ENDMETHOD.ENDCLASS.Pattern 2 : Agrégation d’événements
" Agréger plusieurs événements en un événement récapitulatif
CLASS zcl_event_aggregator IMPLEMENTATION. METHOD on_business_event. " Collecter les événements CASE event_key. WHEN 'TravelApproved' OR 'TravelRejected' OR 'TravelCancelled'. " Compteur en mémoire add_to_statistics( event_key ). ENDCASE.
" Chaque heure : Événement récapitulatif 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 : Filtrage d’événements
" Traiter uniquement certains événements
CLASS zcl_high_value_handler IMPLEMENTATION. METHOD on_business_event. CHECK event_key = 'TravelCreated'.
LOOP AT event_data INTO DATA(ls_event). " Charger les détails du voyage SELECT SINGLE TotalAmount FROM zi_travel WHERE TravelId = @ls_event-%key-TravelId INTO @DATA(lv_amount).
" Seulement les voyages de grande valeur (> 10.000) CHECK lv_amount > 10000.
" Traitement spécial notify_manager( ls_event-%key-TravelId ). require_additional_approval( ls_event-%key-TravelId ). ENDLOOP. ENDMETHOD.ENDCLASS.Remarques importantes / Bonnes pratiques
- Loose Coupling : Les événements découplent Publisher et Consumer
- Asynchrone : Les événements permettent un traitement asynchrone
- Fire & Forget : Le Publisher ne se soucie pas du succès du Consumer
- Idempotence : Les Event Handlers doivent être idempotents (traitement multiple = OK)
- Gestion des erreurs : Les erreurs des Consumers ne doivent pas affecter le Publisher
- Nommage des événements : Temps passé (
TravelApproved, pasApproveTravel) - Payload de l’événement : Seulement les données nécessaires (pas de gros objets)
- Versioning : Ne jamais casser la structure de l’événement (seulement étendre)
- Testing : Tester explicitement les événements (pattern Spy)
- Monitoring : Journaliser et monitorer le traitement des événements
- Logique de retry : Événements échoués dans une queue pour retry
- Event Mesh : Utiliser pour les événements inter-systèmes
- Documentation : Documenter les événements et leurs Consumers
Ressources supplémentaires
- RAP Basics : /rap-basics/
- EML Guide : /eml-entity-manipulation-language/
- RAP Determinations/Validations : /rap-determinations-validations/
- ABAP Cloud : /abap-cloud-definition/