Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
danrega committed Jan 30, 2024
1 parent 7ac1f93 commit 3e98aba
Show file tree
Hide file tree
Showing 14 changed files with 706 additions and 3 deletions.
69 changes: 67 additions & 2 deletions 08_EML_ABAP_for_RAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
- [EML Syntax for Reading Operations](#eml-syntax-for-reading-operations)
- [Dynamic Forms of EML Statements](#dynamic-forms-of-eml-statements)
- [Persisting to the Database](#persisting-to-the-database)
- [EML Statements in ABAP Behavior Pools](#eml-statements-in-abap-behavior-pools)
- [Raising RAP Business Events](#raising-rap-business-events)
- [Additions to EML Statements in ABAP Behavior Pools](#additions-to-eml-statements-in-abap-behavior-pools)
- [RAP Excursions](#rap-excursions)
- [Using Keys and Identifying RAP BO Instances in a Nutshell](#using-keys-and-identifying-rap-bo-instances-in-a-nutshell)
- [RAP Concepts](#rap-concepts)
Expand Down Expand Up @@ -1301,7 +1302,70 @@ ENDIF.

<p align="right"><a href="#top">⬆️ back to top</a></p>

### EML Statements in ABAP Behavior Pools
### Raising RAP Business Events

- [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) can be raised in ABAP behavior pools with [`RAISE ENTITY EVENT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_entity_event.htm) statements.
- Prerequisites:
- `event` specifications are available in the BDEF (e.g. `... event some_evt; ...`). For more details, refer to the [BDL documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_event.htm)
- A [RAP event handler class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_class_glosry.htm) is available that is used to implement [RAP event handler methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_meth_glosry.htm).
- Note that these methods are called asynchronously.
- Similar to RAP handler and saver methods, RAP event handler methods are implemented in the CCIMP include of the RAP event handler class.
- To locally consume RAP business events, a local class that inherits from `CL_ABAP_BEHAVIOR_EVENT_HANDLER` can be implemented in the CCIMP include of a RAP event handler class.
- More information:
- [ABAP for RAP Business Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_events.htm) in the ABAP Keyword Documentation
- [Business Events](https://help.sap.com/docs/abap-cloud/abap-rap/business-events) in the SAP Help Portal

```abap
"---- Syntax for the declaration part of a global RAP event handler class ----
CLASS cl_event_handler DEFINITION PUBLIC FOR EVENTS OF some_bdef.
...
ENDCLASS.
"---- Syntax for the declaration part of a local event handler class ----
"---- in the CCIMP include of a RAP event handler class ----
CLASS lhe_event DEFINITION INHERITING FROM cl_abap_behavior_event_handler.
...
ENDCLASS.
"---- RAP event handler method definition ----
"Notes:
"- Must be defined as instance methods in the private visibility section.
"- The input parameter par is an internal table of type TYPE TABLE FOR EVENT.
"- This type includes the keys of RAP BO instances (and %param, if the event
" is specified with a parameter in the BDEF)
"- The methods do not contain RAP response parameters.
METHODS meth FOR ENTITY EVENT par FOR some_b.def~some_evt.
"---- RAISE ENTITY EVENT statement in an ABP, e.g. the save_modified method ----
"---- in managed scenarios 'with additional save' ----
...
CLASS lsc IMPLEMENTATION.
METHOD save_modified.
"Assumption: An event is specified for create operations in the BDEF as follows
"event created;
IF create-some_bdef IS NOT INITIAL.
RAISE ENTITY EVENT some_bdef~created
FROM VALUE #( FOR <cr> IN create-root ( %key = VALUE #( some_key = <cr>-some_key ) ) ).
ENDIF.
"Assumption: An event is specified for delete operations in the BDEF as follows
"event deleted parameter some_abstract_entity;
"The abstract entity has two parameters, for example, with which additional
"information can be passed.
IF delete-some_bdef IS NOT INITIAL.
RAISE ENTITY EVENT some_bdef~deleted
FROM VALUE #( FOR <del> IN delete-some_bdef (
%key = VALUE #( some_key = <del>-some_key )
%param = VALUE #( par_a = '01'
par_b = 'Item deleted' ) ) ).
ENDIF.
ENDMETHOD.
ENDCLASS.
```

<p align="right"><a href="#top">⬆️ back to top</a></p>

### Additions to EML Statements in ABAP Behavior Pools

- There are a [special additions when using EML in behavior
pools](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeneml_in_abp.htm).
Expand Down Expand Up @@ -1644,6 +1708,7 @@ This cheat sheet is supported by different executable examples demonstrating var
- Demo RAP scenario with a managed RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_m](./src/zcl_demo_abap_rap_ext_num_m.clas.abap)
- Demo RAP scenario with an unmanaged RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_u](./src/zcl_demo_abap_rap_ext_num_u.clas.abap)
- Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering [zcl_demo_abap_rap_draft_ln_m](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap)
- Demonstrating the local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) in the context of a RAP demo scenario (managed RAP BO with managed [internal numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_numbering_glosry.htm) and [additional save](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_add_save_glosry.htm)): [zcl_demo_abap_rap_m_as](./src/zcl_demo_abap_rap_m_as.clas.abap)
> **💡 Note**<br>
> - To reduce the complexity, the executable examples only focus on the technical side. ABAP classes play the role of a RAP BO consumer here.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ ABAP cheat sheets[^1] ...
|[Constructor Expressions](05_Constructor_Expressions.md)| Covers constructor expressions with operators such as `VALUE`, `CORRESPONDING`, `NEW`, `CONV`, `EXACT`, `REF`, `CAST`, `COND`, `SWITCH`, `FILTER`, `REDUCE`, iteration expressions with `FOR`, `LET` expressions | [zcl_demo_abap_constructor_expr](./src/zcl_demo_abap_constructor_expr.clas.abap) |
|[Dynamic Programming](06_Dynamic_Programming.md)| Covers field symbols and data references as supporting elements for dynamic programming, dynamic ABAP syntax components, runtime type services (RTTS), i. e. runtime type identification (RTTI) and runtime type creation (RTTC) | [zcl_demo_abap_dynamic_prog](./src/zcl_demo_abap_dynamic_prog.clas.abap) |
|[String Processing](07_String_Processing.md)| Creating strings and assigning values, chaining strings, string templates, concatenating, splitting, modifying strings, searching and replacing, regular expressions | [zcl_demo_abap_string_proc](./src/zcl_demo_abap_string_proc.clas.abap) |
|[ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md)| Setting EML in the context of RAP, standard (create, read, update, delete) and non-standard operations (actions) | <ul><li>[Demo RAP scenario with a managed RAP BO, external numbering (zcl_demo_abap_rap_ext_num_m)](./src/zcl_demo_abap_rap_ext_num_m.clas.abap)</li><br><li>[Demo RAP scenario with an unmanaged RAP BO, external numbering (zcl_demo_abap_rap_ext_num_u)](./src/zcl_demo_abap_rap_ext_num_u.clas.abap)</li><br><li>[Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering (zcl_demo_abap_rap_draft_ln_m)](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) <br>Note that this example can also be checked out using the preview version of an SAP Fiori UI. Check the comments in the class for the steps.</li></ul> |
|[ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md)| Setting EML in the context of RAP, standard (create, read, update, delete) and non-standard operations (actions) | <ul><li>[Demo RAP scenario with a managed RAP BO, external numbering (zcl_demo_abap_rap_ext_num_m)](./src/zcl_demo_abap_rap_ext_num_m.clas.abap)</li><br><li>[Demo RAP scenario with an unmanaged RAP BO, external numbering (zcl_demo_abap_rap_ext_num_u)](./src/zcl_demo_abap_rap_ext_num_u.clas.abap)</li><br><li>[Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering (zcl_demo_abap_rap_draft_ln_m)](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) <br>Note that this example can also be checked out using the preview version of an SAP Fiori UI. Check the comments in the class for the steps.</li><br><li>[Demonstrating the local consumption of RAP business events in the context of a RAP demo scenario, managed RAP BO with managed internal numbering and additional save (zcl_demo_abap_rap_m_as)](./src/zcl_demo_abap_rap_m_as.clas.abap)</li></ul> |
|[Excursion Down to Bits and Bytes](09_Bits_and_Bytes.md)|Covers the technical background of data types and data objects|-|
|[ABAP SQL: Working with Hierarchies](10_ABAP_SQL_Hierarchies.md)|Summarizes the functions ABAP SQL offers together with ABAP CDS for working with hierarchical data that is stored in database tables|-|
|[Internal Tables: Grouping](11_Internal_Tables_Grouping.md)|Covers the `GROUP BY` clause in statements for internal tables.|[zcl_demo_abap_sql_group_by](./src/zcl_demo_abap_sql_group_by.clas.abap)|
Expand Down
7 changes: 7 additions & 0 deletions src/zbp_demo_abap_rap_ro_m_as.clas.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CLASS zbp_demo_abap_rap_ro_m_as DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_ro_m_as.
PUBLIC SECTION.
CLASS-DATA num_raised_events TYPE i.
ENDCLASS.

CLASS zbp_demo_abap_rap_ro_m_as IMPLEMENTATION.
ENDCLASS.
109 changes: 109 additions & 0 deletions src/zbp_demo_abap_rap_ro_m_as.clas.locals_imp.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
CLASS lhc_zdemo_abap_rap_ro_m_as DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.

METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR root RESULT result.

METHODS calc FOR MODIFY
IMPORTING keys FOR ACTION root~calc.

METHODS det_modify FOR DETERMINE ON MODIFY
IMPORTING keys FOR root~det_modify.

ENDCLASS.

CLASS lhc_zdemo_abap_rap_ro_m_as IMPLEMENTATION.

METHOD get_global_authorizations.
ENDMETHOD.

METHOD calc.
READ ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
FIELDS ( num1 num2 arithm_op crea_date_time lchg_date_time ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_calc)
FAILED DATA(f).

DATA(timestamp) = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) ).

LOOP AT lt_calc ASSIGNING FIELD-SYMBOL(<calc>).
TRY.
<calc>-calc_result = SWITCH #( <calc>-arithm_op
WHEN `+` THEN |{ CONV decfloat34( <calc>-num1 + <calc>-num2 ) STYLE = SIMPLE }|
WHEN `-` THEN |{ CONV decfloat34( <calc>-num1 - <calc>-num2 ) STYLE = SIMPLE }|
WHEN `*` THEN |{ CONV decfloat34( <calc>-num1 * <calc>-num2 ) STYLE = SIMPLE }|
WHEN `/` THEN |{ CONV decfloat34( <calc>-num1 / <calc>-num2 ) STYLE = SIMPLE }|
WHEN `P` THEN |{ CONV decfloat34( ipow( base = <calc>-num1 exp = <calc>-num2 ) ) STYLE = SIMPLE }|
ELSE `Wrong operator` ).

"Handling the fact that ABAP allows division by zero if the dividend itself is zero.
IF <calc>-num1 = 0 AND <calc>-num2 = 0 AND <calc>-arithm_op = `/`.
<calc>-calc_result = `Division by 0`.
ENDIF.
CATCH cx_sy_zerodivide.
<calc>-calc_result = `Division by 0`.
CATCH cx_sy_arithmetic_overflow.
<calc>-calc_result = `Overflow error`.
ENDTRY.
ENDLOOP.

MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
UPDATE FIELDS ( calc_result )
WITH CORRESPONDING #( lt_calc ).
ENDMETHOD.

METHOD det_modify.
MODIFY ENTITY IN LOCAL MODE zdemo_abap_rap_ro_m_as
EXECUTE calc
FROM CORRESPONDING #( keys ).
ENDMETHOD.

ENDCLASS.

CLASS lsc_zdemo_abap_rap_ro_m_as DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.

METHODS save_modified REDEFINITION.

METHODS cleanup_finalize REDEFINITION.

ENDCLASS.

CLASS lsc_zdemo_abap_rap_ro_m_as IMPLEMENTATION.

METHOD save_modified.
IF create-root IS NOT INITIAL.
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~created
FROM VALUE #( FOR <cr> IN create-root (
%key = VALUE #( id = <cr>-id ) ) ).

zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( create-root ).
ENDIF.

IF update-root IS NOT INITIAL.
"Demonstrating the BDEF derived type TYPE TABLE FOR EVENT
DATA evt_tab_up TYPE TABLE FOR EVENT zdemo_abap_rap_ro_m_as~updated.

evt_tab_up = VALUE #( FOR <up> IN update-root INDEX INTO updidx (
%key = VALUE #( id = <up>-id )
%param = VALUE #( col1 = 'Event raised'
col2 = |UPDATED ({ updidx })| ) ) ).
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~updated FROM evt_tab_up.

zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( update-root ).
ENDIF.

IF delete-root IS NOT INITIAL.
RAISE ENTITY EVENT zdemo_abap_rap_ro_m_as~deleted
FROM VALUE #( FOR <del> IN delete-root INDEX INTO delidx (
%key = VALUE #( id = <del>-id )
%param = VALUE #( col1 = 'Event raised'
col2 = |DELETED ({ delidx })| ) ) ).

zbp_demo_abap_rap_ro_m_as=>num_raised_events = zbp_demo_abap_rap_ro_m_as=>num_raised_events + lines( delete-root ).
ENDIF.
ENDMETHOD.

METHOD cleanup_finalize.
ENDMETHOD.

ENDCLASS.
23 changes: 23 additions & 0 deletions src/zcl_demo_abap_rap_evt_handler.clas.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**********************************************************************
* Note:
*
* - This class is the RAP event handler class for zdemo_abap_rap_ro_m_as.
*
* - The RAP business events in this example are raised using RAISE
* ENTITY EVENT statements in the save_modified saver method that
* is implemented in the CCIMP include of the ABAP behavior pool
* zbp_demo_abap_rap_ro_m_as.
*
**********************************************************************

CLASS zcl_demo_abap_rap_evt_handler DEFINITION
PUBLIC ABSTRACT FINAL
FOR EVENTS OF zdemo_abap_rap_ro_m_as.

PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.

CLASS zcl_demo_abap_rap_evt_handler IMPLEMENTATION.
ENDCLASS.
75 changes: 75 additions & 0 deletions src/zcl_demo_abap_rap_evt_handler.clas.locals_imp.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
CLASS lhe_event DEFINITION INHERITING FROM cl_abap_behavior_event_handler.

PRIVATE SECTION.

METHODS on_updated FOR ENTITY EVENT
updated FOR root~updated.

METHODS on_deleted FOR ENTITY EVENT
deleted FOR root~deleted.

METHODS on_created FOR ENTITY EVENT
created FOR root~created.

DATA evt_log TYPE TABLE OF zdemo_abap_draft WITH EMPTY KEY.
ENDCLASS.

CLASS lhe_event IMPLEMENTATION.

"Note:
"- For this example, database table entries are created for the individual
" RAP BO instances that are imported into the event handler methods.
"- The transactional phases are implicitly set when RAP business events are
" consumed locally. This means that RAP event handler methods are started in
" the modify phase when called. If database modifications are to be implemented
" in RAP event handler methods, you must explicitly activate the save phase to
" avoid causing errors detected by the controlled SAP LUW.

METHOD on_created.
cl_abap_tx=>save( ).
LOOP AT created ASSIGNING FIELD-SYMBOL(<created>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <created>-id }" / Event CREATED raised|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.

METHOD on_updated.
cl_abap_tx=>save( ).
LOOP AT updated ASSIGNING FIELD-SYMBOL(<updated>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <updated>-id }" / %param: col1: "{ <updated>-%param-col1 }" col2: "{ <updated>-%param-col2 }"|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.

METHOD on_deleted.
cl_abap_tx=>save( ).
LOOP AT deleted ASSIGNING FIELD-SYMBOL(<deleted>).
TRY.
APPEND VALUE #( id = cl_system_uuid=>create_uuid_x16_static( )
draftuuid = cl_system_uuid=>create_uuid_x16_static( )
calc_result = |Instance key: "{ <deleted>-id }" / %param: col1: "{ <deleted>-%param-col1 }" col2: "{ <deleted>-%param-col2 }"|
crea_date_time = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) )
) TO evt_log.
CATCH cx_uuid_error INTO DATA(err).
ASSERT err IS INITIAL.
ENDTRY.
MODIFY zdemo_abap_draft FROM TABLE @evt_log.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Loading

0 comments on commit 3e98aba

Please sign in to comment.