ABAP Events: EVENTS, RAISE EVENT and SET HANDLER

Category
ABAP-Statements
Published
Author
Johannes

Events enable loose coupling between objects in ABAP. An object (publisher) can trigger events without knowing who will react to them. Other objects (subscribers) register as handlers and are notified when events occur.

Basic Concept

  • EVENTS: Declares an event in a class
  • RAISE EVENT: Triggers the event (publisher)
  • SET HANDLER: Registers a method as event handler (subscriber)
  • FOR: Specifies which object the handler applies to

Syntax

Declare Event

CLASS <classname> DEFINITION.
EVENTS: <eventname>
[ EXPORTING VALUE(<parameter>) TYPE <type> ].
ENDCLASS.

Trigger Event

RAISE EVENT <eventname>
[ EXPORTING <parameter> = <value> ].

Register Handler

SET HANDLER <handler_object>-><methodname>
FOR <sender_object>.
" For all instances
SET HANDLER <handler_object>-><methodname>
FOR ALL INSTANCES.

Examples

1. Simple Event

" Publisher class: Triggers events
CLASS lcl_button DEFINITION.
PUBLIC SECTION.
EVENTS: clicked.
METHODS: click.
ENDCLASS.
CLASS lcl_button IMPLEMENTATION.
METHOD click.
WRITE: / 'Button was clicked'.
RAISE EVENT clicked.
ENDMETHOD.
ENDCLASS.
" Subscriber class: Reacts to events
CLASS lcl_form DEFINITION.
PUBLIC SECTION.
METHODS: on_button_clicked FOR EVENT clicked OF lcl_button.
ENDCLASS.
CLASS lcl_form IMPLEMENTATION.
METHOD on_button_clicked.
WRITE: / 'Form: Button click processed!'.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_button TYPE REF TO lcl_button,
lo_form TYPE REF TO lcl_form.
lo_button = NEW #( ).
lo_form = NEW #( ).
" Register handler
SET HANDLER lo_form->on_button_clicked FOR lo_button.
" Trigger event
lo_button->click( ).
" Output:
" Button was clicked
" Form: Button click processed!

2. Event with Parameters

CLASS lcl_order_processor DEFINITION.
PUBLIC SECTION.
" Event with export parameters
EVENTS: order_completed
EXPORTING VALUE(ev_order_id) TYPE i
VALUE(ev_amount) TYPE p DECIMALS 2.
METHODS: process_order IMPORTING iv_order_id TYPE i
iv_amount TYPE p.
ENDCLASS.
CLASS lcl_order_processor IMPLEMENTATION.
METHOD process_order.
WRITE: / |Order { iv_order_id } processed.|.
" Trigger event with data
RAISE EVENT order_completed
EXPORTING
ev_order_id = iv_order_id
ev_amount = iv_amount.
ENDMETHOD.
ENDCLASS.
CLASS lcl_notification_service DEFINITION.
PUBLIC SECTION.
" Handler method with SENDER
METHODS: on_order_completed
FOR EVENT order_completed OF lcl_order_processor
IMPORTING ev_order_id ev_amount sender.
ENDCLASS.
CLASS lcl_notification_service IMPLEMENTATION.
METHOD on_order_completed.
WRITE: / |Notification: Order { ev_order_id }|.
WRITE: / |Amount: { ev_amount } EUR|.
" sender contains reference to the triggering object
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_processor TYPE REF TO lcl_order_processor,
lo_notification TYPE REF TO lcl_notification_service.
lo_processor = NEW #( ).
lo_notification = NEW #( ).
SET HANDLER lo_notification->on_order_completed FOR lo_processor.
lo_processor->process_order( iv_order_id = 1001 iv_amount = '250.00' ).
" Output:
" Order 1001 processed.
" Notification: Order 1001
" Amount: 250.00 EUR

3. Multiple Handlers for One Event

CLASS lcl_logger DEFINITION.
PUBLIC SECTION.
METHODS: on_order_completed
FOR EVENT order_completed OF lcl_order_processor
IMPORTING ev_order_id ev_amount.
ENDCLASS.
CLASS lcl_logger IMPLEMENTATION.
METHOD on_order_completed.
WRITE: / |LOG: Order { ev_order_id } - { ev_amount } EUR|.
ENDMETHOD.
ENDCLASS.
CLASS lcl_statistics DEFINITION.
PUBLIC SECTION.
DATA: mv_total_orders TYPE i,
mv_total_amount TYPE p DECIMALS 2.
METHODS: on_order_completed
FOR EVENT order_completed OF lcl_order_processor
IMPORTING ev_order_id ev_amount.
ENDCLASS.
CLASS lcl_statistics IMPLEMENTATION.
METHOD on_order_completed.
mv_total_orders = mv_total_orders + 1.
mv_total_amount = mv_total_amount + ev_amount.
WRITE: / |STATS: { mv_total_orders } orders, Total: { mv_total_amount }|.
ENDMETHOD.
ENDCLASS.
" Usage - Register multiple handlers
DATA: lo_processor TYPE REF TO lcl_order_processor,
lo_notify TYPE REF TO lcl_notification_service,
lo_logger TYPE REF TO lcl_logger,
lo_statistics TYPE REF TO lcl_statistics.
lo_processor = NEW #( ).
lo_notify = NEW #( ).
lo_logger = NEW #( ).
lo_statistics = NEW #( ).
" Register all handlers
SET HANDLER: lo_notify->on_order_completed FOR lo_processor,
lo_logger->on_order_completed FOR lo_processor,
lo_statistics->on_order_completed FOR lo_processor.
lo_processor->process_order( iv_order_id = 1001 iv_amount = '100.00' ).
lo_processor->process_order( iv_order_id = 1002 iv_amount = '200.00' ).
" All handlers are called!

4. FOR ALL INSTANCES

CLASS lcl_global_logger DEFINITION.
PUBLIC SECTION.
METHODS: on_any_order_completed
FOR EVENT order_completed OF lcl_order_processor
IMPORTING ev_order_id sender.
ENDCLASS.
CLASS lcl_global_logger IMPLEMENTATION.
METHOD on_any_order_completed.
WRITE: / |Global Log: Order { ev_order_id } processed by Processor|.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_processor1 TYPE REF TO lcl_order_processor,
lo_processor2 TYPE REF TO lcl_order_processor,
lo_global_log TYPE REF TO lcl_global_logger.
lo_processor1 = NEW #( ).
lo_processor2 = NEW #( ).
lo_global_log = NEW #( ).
" Handler for ALL instances of the class
SET HANDLER lo_global_log->on_any_order_completed FOR ALL INSTANCES.
lo_processor1->process_order( iv_order_id = 1 iv_amount = 50 ).
lo_processor2->process_order( iv_order_id = 2 iv_amount = 75 ).
" Both are logged!

5. Deactivate Handler

" Remove handler
SET HANDLER lo_notify->on_order_completed FOR lo_processor ACTIVATION space.
" Or explicitly with abap_false
SET HANDLER lo_logger->on_order_completed
FOR lo_processor
ACTIVATION abap_false.
" Reactivate handler
SET HANDLER lo_logger->on_order_completed
FOR lo_processor
ACTIVATION abap_true.

6. Static Events (CLASS-EVENTS)

CLASS lcl_application DEFINITION.
PUBLIC SECTION.
" Static event - belongs to class, not instance
CLASS-EVENTS: application_started.
CLASS-METHODS: start.
ENDCLASS.
CLASS lcl_application IMPLEMENTATION.
METHOD start.
WRITE: / 'Application starting...'.
RAISE EVENT application_started.
ENDMETHOD.
ENDCLASS.
CLASS lcl_startup_handler DEFINITION.
PUBLIC SECTION.
" Handler for class event
METHODS: on_app_started
FOR EVENT application_started OF lcl_application.
ENDCLASS.
CLASS lcl_startup_handler IMPLEMENTATION.
METHOD on_app_started.
WRITE: / 'Startup handler: Initialization running...'.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_handler TYPE REF TO lcl_startup_handler.
lo_handler = NEW #( ).
" For class events: FOR lcl_application (not FOR instance)
SET HANDLER lo_handler->on_app_started FOR lcl_application.
lcl_application=>start( ).

7. Events in Interfaces

INTERFACE lif_observable.
EVENTS: data_changed
EXPORTING VALUE(ev_new_value) TYPE string.
ENDINTERFACE.
CLASS lcl_model DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_observable.
METHODS: set_value IMPORTING iv_value TYPE string.
PRIVATE SECTION.
DATA: mv_value TYPE string.
ENDCLASS.
CLASS lcl_model IMPLEMENTATION.
METHOD set_value.
mv_value = iv_value.
" Trigger event from interface
RAISE EVENT lif_observable~data_changed
EXPORTING ev_new_value = mv_value.
ENDMETHOD.
ENDCLASS.
CLASS lcl_view DEFINITION.
PUBLIC SECTION.
" Handler for interface event
METHODS: on_data_changed
FOR EVENT data_changed OF lif_observable
IMPORTING ev_new_value.
ENDCLASS.
CLASS lcl_view IMPLEMENTATION.
METHOD on_data_changed.
WRITE: / |View updated: { ev_new_value }|.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_model TYPE REF TO lcl_model,
lo_view TYPE REF TO lcl_view.
lo_model = NEW #( ).
lo_view = NEW #( ).
SET HANDLER lo_view->on_data_changed FOR lo_model.
lo_model->set_value( 'New value' ).
" Output: View updated: New value

8. Complete Observer Pattern

" Subject Interface
INTERFACE lif_subject.
METHODS: attach IMPORTING io_observer TYPE REF TO lif_observer,
detach IMPORTING io_observer TYPE REF TO lif_observer,
notify.
ENDINTERFACE.
" Observer Interface
INTERFACE lif_observer.
METHODS: update IMPORTING iv_state TYPE string.
ENDINTERFACE.
" Concrete Subject
CLASS lcl_weather_station DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_subject.
EVENTS: weather_changed EXPORTING VALUE(ev_weather) TYPE string.
METHODS: set_weather IMPORTING iv_weather TYPE string.
PRIVATE SECTION.
DATA: mt_observers TYPE TABLE OF REF TO lif_observer,
mv_weather TYPE string.
ENDCLASS.
CLASS lcl_weather_station IMPLEMENTATION.
METHOD lif_subject~attach.
APPEND io_observer TO mt_observers.
ENDMETHOD.
METHOD lif_subject~detach.
DELETE mt_observers WHERE table_line = io_observer.
ENDMETHOD.
METHOD lif_subject~notify.
LOOP AT mt_observers INTO DATA(lo_observer).
lo_observer->update( mv_weather ).
ENDLOOP.
ENDMETHOD.
METHOD set_weather.
mv_weather = iv_weather.
lif_subject~notify( ).
RAISE EVENT weather_changed EXPORTING ev_weather = mv_weather.
ENDMETHOD.
ENDCLASS.
" Concrete Observer
CLASS lcl_phone_display DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_observer.
METHODS: on_weather_changed
FOR EVENT weather_changed OF lcl_weather_station
IMPORTING ev_weather.
ENDCLASS.
CLASS lcl_phone_display IMPLEMENTATION.
METHOD lif_observer~update.
WRITE: / |Phone Display: { iv_state }|.
ENDMETHOD.
METHOD on_weather_changed.
WRITE: / |Phone Event: { ev_weather }|.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_station TYPE REF TO lcl_weather_station,
lo_phone TYPE REF TO lcl_phone_display.
lo_station = NEW #( ).
lo_phone = NEW #( ).
" Observer Pattern
lo_station->lif_subject~attach( lo_phone ).
" Or with events
SET HANDLER lo_phone->on_weather_changed FOR lo_station.
lo_station->set_weather( 'Sunny, 25°C' ).

9. SENDER Parameter

CLASS lcl_multi_button_handler DEFINITION.
PUBLIC SECTION.
METHODS: on_button_clicked
FOR EVENT clicked OF lcl_button
IMPORTING sender. " Reference to triggering object
ENDCLASS.
CLASS lcl_multi_button_handler IMPLEMENTATION.
METHOD on_button_clicked.
" sender contains the reference to the clicked button
DATA(lo_button) = sender.
WRITE: / 'A button was clicked'.
" Type check and cast possible
IF sender IS INSTANCE OF lcl_button.
" Access button-specific methods
ENDIF.
ENDMETHOD.
ENDCLASS.
" Usage
DATA: lo_btn1 TYPE REF TO lcl_button,
lo_btn2 TYPE REF TO lcl_button,
lo_handler TYPE REF TO lcl_multi_button_handler.
lo_btn1 = NEW #( ).
lo_btn2 = NEW #( ).
lo_handler = NEW #( ).
SET HANDLER lo_handler->on_button_clicked FOR ALL INSTANCES.
lo_btn1->click( ). " sender = lo_btn1
lo_btn2->click( ). " sender = lo_btn2

10. Practical Example: ALV Event Handling

CLASS lcl_alv_handler DEFINITION.
PUBLIC SECTION.
METHODS: on_double_click
FOR EVENT double_click OF cl_salv_events_table
IMPORTING row column.
METHODS: on_link_click
FOR EVENT link_click OF cl_salv_events_table
IMPORTING row column.
ENDCLASS.
CLASS lcl_alv_handler IMPLEMENTATION.
METHOD on_double_click.
WRITE: / |Double click on row { row }, column { column }|.
ENDMETHOD.
METHOD on_link_click.
WRITE: / |Link clicked in row { row }, column { column }|.
ENDMETHOD.
ENDCLASS.
" Usage with SALV
DATA: lo_alv TYPE REF TO cl_salv_table,
lo_events TYPE REF TO cl_salv_events_table,
lo_handler TYPE REF TO lcl_alv_handler.
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = lo_alv
CHANGING t_table = lt_data
).
" Get events
lo_events = lo_alv->get_event( ).
" Register handlers
lo_handler = NEW #( ).
SET HANDLER: lo_handler->on_double_click FOR lo_events,
lo_handler->on_link_click FOR lo_events.
lo_alv->display( ).
CATCH cx_salv_msg.
ENDTRY.

Event Types

TypeDeclarationSET HANDLER FOR
Instance eventEVENTSSpecific instance
Class eventCLASS-EVENTSClass itself
Interface eventEVENTS in InterfaceImplementing class

Important Notes / Best Practice

  • Events enable loose coupling – publisher doesn’t know subscribers.
  • SENDER contains the reference to the triggering object.
  • FOR ALL INSTANCES for global handlers (logging, monitoring).
  • ACTIVATION space/abap_false to deactivate handlers.
  • Events are synchronous – handlers execute immediately.
  • CLASS-EVENTS for class-wide events without instance.
  • Use INTERFACE for events with loose coupling.
  • Observer Pattern ideal for UI updates and notifications.
  • Handler methods must have the correct signature (FOR EVENT ... OF).
  • Be careful with circular event chains – can cause infinite loops.