Update
This commit is contained in:
@@ -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)
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
|
||||
@@ -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)|
|
||||
|
||||
7
src/zbp_demo_abap_rap_ro_m_as.clas.abap
Normal file
7
src/zbp_demo_abap_rap_ro_m_as.clas.abap
Normal file
@@ -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
src/zbp_demo_abap_rap_ro_m_as.clas.locals_imp.abap
Normal file
109
src/zbp_demo_abap_rap_ro_m_as.clas.locals_imp.abap
Normal file
@@ -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
src/zcl_demo_abap_rap_evt_handler.clas.abap
Normal file
23
src/zcl_demo_abap_rap_evt_handler.clas.abap
Normal file
@@ -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
src/zcl_demo_abap_rap_evt_handler.clas.locals_imp.abap
Normal file
75
src/zcl_demo_abap_rap_evt_handler.clas.locals_imp.abap
Normal file
@@ -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.
|
||||
318
src/zcl_demo_abap_rap_m_as.clas.abap
Normal file
318
src/zcl_demo_abap_rap_m_as.clas.abap
Normal file
@@ -0,0 +1,318 @@
|
||||
***********************************************************************
|
||||
*
|
||||
* RAP BO consumer for a RAP demo scenario:
|
||||
* Managed RAP BO with managed internal numbering and additional save
|
||||
* demonstrating the local consumption of RAP business events
|
||||
*
|
||||
* -------------------------- PURPOSE ----------------------------------
|
||||
* - Primarily, the example demonstrates the local consumption of RAP
|
||||
* business events.
|
||||
* - For that purpose, the BDEF defines three events. Two of them are
|
||||
* specified with a parameter. The events are raised for create, update
|
||||
* and delete operations.
|
||||
* - The example implementation in this class (the RAP BO consumer)
|
||||
* contains three ABAP EML modify requests: a RAP create, update and
|
||||
* delete operation. For each of the operations, an event is raised
|
||||
* using a RAISE ENTITY EVENT statement. The events are raised in the
|
||||
* save_modified RAP saver method in the CCIMP include of the behavior
|
||||
* pool.
|
||||
* - When the events are raised, the RAP event handler methods are called
|
||||
* asynchronously. To demonstrate the effect of the events, a database
|
||||
* table representing a log table is populated.
|
||||
* - In the output of the example, the content of internal tables is
|
||||
* displayed to demonstrate the effect of the RAP operations by
|
||||
* selecting from the database table where the RAP BO instances are
|
||||
* persisted to after each RAP operation. Additionally, the content
|
||||
* of an internal table is displayed including the entries that have been
|
||||
* inserted into the log database table by the event handler methods.
|
||||
* In this self-contained example, this 'log database table' is just a
|
||||
* database table that is used to store some entries triggered by the RAP
|
||||
* events for visualization purposes. You can imagine that, for example,
|
||||
* the sending of an email is triggered there, or the application log is
|
||||
* filled, and so on. The log table is used in another RAP example as
|
||||
* draft table. The draft concept is not relevant for this simplified
|
||||
* example here.
|
||||
* - Note the comments in the example code. You can check out the
|
||||
* asynchronity by commenting out the WAIT statement further down.
|
||||
*
|
||||
* ----------------- RELATED ARTIFACTS OF THE EXAMPLE ------------------*
|
||||
* - RAP BO consumer: zcl_demo_abap_rap_m_as (this class here)
|
||||
* - RAP BO provider (ABAP behavior pool): zbp_demo_abap_rap_ro_m_as
|
||||
* - RAP event handler: zcl_demo_abap_rap_evt_handler
|
||||
* - BDEF: zdemo_abap_rap_ro_m_as
|
||||
* - More artifacts are related such as database tables, CDS views, and
|
||||
* an abstract entity (zdemo_abap_abstract_ent; used for the parameter
|
||||
* specifications for the events in the BDEF)
|
||||
*
|
||||
* ----------------------- GETTING STARTED -----------------------------
|
||||
* - Open the class with the ABAP development tools for Eclipse (ADT).
|
||||
* - Choose F9 to run the class.
|
||||
* - Check the console output.
|
||||
* - To understand the context and the ABAP syntax used, check the notes
|
||||
* included in the class as comments or refer to the respective topic
|
||||
* in the ABAP Keyword Documentation.
|
||||
* - Due to the amount of output in the console, the examples include
|
||||
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
|
||||
* sections. Plus, the variable name is displayed in most cases. Hence,
|
||||
* to easier and faster find the relevant output in the console, just
|
||||
* search in the console for the number/variable name (CTRL+F in the
|
||||
* console) or use the debugger.
|
||||
*
|
||||
* ----------------------------- NOTE -----------------------------------
|
||||
* This simplified example is not a real life scenario and rather
|
||||
* focuses on the technical side by giving an idea how the communication
|
||||
* and data exchange between a RAP BO consumer, which is a class
|
||||
* in this case, and RAP BO provider can work. Additionally, it shows
|
||||
* how the methods for non-standard RAP BO operations might be
|
||||
* self-implemented in an ABP. The example is intentionally kept
|
||||
* short and simple and focuses on specific RAP aspects. For this reason,
|
||||
* the example might not fully meet the requirements of the RAP BO contract.
|
||||
*
|
||||
* The code presented in this class is intended only to support the ABAP
|
||||
* cheat sheets. It is not intended for direct use in a production system
|
||||
* environment. The code examples in the ABAP cheat sheets are primarily
|
||||
* intended to provide a better explanation and visualization of the
|
||||
* syntax and semantics of ABAP statements, not to solve concrete
|
||||
* programming tasks. For production application programs, you should
|
||||
* always work out your own solution for each individual case. There is
|
||||
* no guarantee for the correctness or completeness of the code.
|
||||
* Furthermore, there is no legal responsibility or liability for any
|
||||
* errors or their consequences that may occur when using the the example
|
||||
* code.
|
||||
*
|
||||
***********************************************************************
|
||||
"! <p class="shorttext synchronized">ABAP cheat sheet: Local consumption of RAP Business Events</p>
|
||||
"! Example to demonstrate local consumption of RAP business events in the context of a RAP demo scenario (managed RAP BO with managed internal numbering and additional save).
|
||||
"! The class represents a RAP BO consumer.<br>Choose F9 in ADT to run the class.
|
||||
CLASS zcl_demo_abap_rap_m_as DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES: if_oo_adt_classrun.
|
||||
|
||||
CLASS-METHODS:
|
||||
class_constructor.
|
||||
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_demo_abap_rap_m_as IMPLEMENTATION.
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
out->write( |ABAP Cheat Sheet Example: Local Consumption of RAP Business Events\n\n| ).
|
||||
"RAP create operation that creates multiple calculations
|
||||
"Note the AUTO FILL CID addition with which the required %cid values
|
||||
"for RAP BO instances are created automatically. Since the scenario is
|
||||
"managed internal numbering, the 'id' field is assigned an appropriate value
|
||||
"automatically by the RAP framework.
|
||||
MODIFY ENTITY zdemo_abap_rap_ro_m_as
|
||||
CREATE AUTO FILL CID
|
||||
FIELDS ( num1 arithm_op num2 )
|
||||
WITH VALUE #( ( num1 = 1
|
||||
arithm_op = '+'
|
||||
num2 = 2 )
|
||||
( num1 = 5
|
||||
arithm_op = '-'
|
||||
num2 = 30 )
|
||||
( num1 = 3
|
||||
arithm_op = '*'
|
||||
num2 = 3 )
|
||||
( num1 = 7
|
||||
arithm_op = '/'
|
||||
num2 = 5 )
|
||||
( num1 = 2
|
||||
arithm_op = 'P'
|
||||
num2 = 4 )
|
||||
( num1 = 10
|
||||
arithm_op = 'P'
|
||||
num2 = 1000000000 )
|
||||
( num1 = 2
|
||||
arithm_op = '/'
|
||||
num2 = 0 ) )
|
||||
MAPPED DATA(m_cr)
|
||||
FAILED DATA(f_cr)
|
||||
REPORTED DATA(r_cr).
|
||||
|
||||
COMMIT ENTITIES.
|
||||
|
||||
IF sy-subrc <> 0.
|
||||
out->write( `An issue occurred in the RAP save sequence.` ).
|
||||
ENDIF.
|
||||
|
||||
"Getting and displaying persisted instances to show the effect of the
|
||||
"EML MODIFY statement
|
||||
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
|
||||
FROM zdemo_abap_tabca
|
||||
ORDER BY lchg_date_time
|
||||
INTO TABLE @DATA(dbtab_entries).
|
||||
|
||||
out->write( `Database table entries after the create operation`
|
||||
)->write( dbtab_entries
|
||||
)->write( |\n| ).
|
||||
|
||||
**********************************************************************
|
||||
|
||||
"RAP update operation
|
||||
"In the example, all RAP BO instances that were created above are
|
||||
"updated. Here, the second number is updated with a random
|
||||
"integer (from the value range 1 - 10). For this purpose, the
|
||||
"cl_abap_random_int class is used.
|
||||
"The reference to existing instances is made using entries in the
|
||||
"mapped reponse table from above (it contains all keys of the created
|
||||
"RAP BO instances).
|
||||
IF m_cr-root IS NOT INITIAL.
|
||||
MODIFY ENTITY zdemo_abap_rap_ro_m_as
|
||||
UPDATE FIELDS ( num2 )
|
||||
WITH VALUE #( FOR wa IN m_cr-root ( id = wa-id
|
||||
num2 = cl_abap_random_int=>create(
|
||||
seed = cl_abap_random=>seed( )
|
||||
min = 1
|
||||
max = 10 )->get_next( ) ) )
|
||||
FAILED DATA(f_upd)
|
||||
REPORTED DATA(r_upd).
|
||||
|
||||
COMMIT ENTITIES.
|
||||
|
||||
IF sy-subrc <> 0.
|
||||
out->write( `An issue occurred in the RAP save sequence.` ).
|
||||
ENDIF.
|
||||
|
||||
"Getting and displaying persisted instances to show the effect of the
|
||||
"EML MODIFY statement
|
||||
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
|
||||
FROM zdemo_abap_tabca
|
||||
ORDER BY lchg_date_time
|
||||
INTO TABLE @dbtab_entries.
|
||||
|
||||
out->write( `Database table entries after the update operation`
|
||||
)->write( dbtab_entries
|
||||
)->write( |\n| ).
|
||||
ENDIF.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
"RAP delete operation
|
||||
"As above, the reference to existing RAP BO instances is made
|
||||
"using entries in the mapped response table. In the example,
|
||||
"the first three instances created are deleted.
|
||||
IF lines( m_cr-root ) > 3.
|
||||
MODIFY ENTITY zdemo_abap_rap_ro_m_as
|
||||
DELETE FROM VALUE #( ( id = m_cr-root[ 1 ]-id )
|
||||
( id = m_cr-root[ 2 ]-id )
|
||||
( id = m_cr-root[ 3 ]-id ) )
|
||||
FAILED DATA(f_del)
|
||||
REPORTED DATA(r_del).
|
||||
|
||||
COMMIT ENTITIES.
|
||||
|
||||
IF sy-subrc <> 0.
|
||||
out->write( `An issue occurred in the RAP save sequence.` ).
|
||||
ENDIF.
|
||||
|
||||
"Getting and displaying persisted instances to show the effect of the
|
||||
"EML MODIFY statement
|
||||
SELECT id, num1, arithm_op, num2, calc_result, crea_date_time, lchg_date_time
|
||||
FROM zdemo_abap_tabca
|
||||
ORDER BY lchg_date_time
|
||||
INTO TABLE @dbtab_entries.
|
||||
|
||||
out->write( `Database table entries after the delete operation`
|
||||
)->write( dbtab_entries
|
||||
)->write( |\n| ).
|
||||
ENDIF.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
"Note:
|
||||
"- Due to the asynchronous call of the events, a WAIT statement
|
||||
" is included to give the events some time in this self-contained example,
|
||||
" i.e. so that all the database table entries that are created in the
|
||||
" RAP event handler method can be retrieved and displayed.
|
||||
"- In the RAP event handler method implementation, note the cl_abap_tx=>save( ).
|
||||
" method call. This explicit activation of the 'save' transactional phase
|
||||
" is required because, when called, the methods are started in the
|
||||
" 'modify' transactional phase. In the modify phase, database modification
|
||||
" statements are not allowed. If the save phase is not activated,
|
||||
" a following database modification statement results in an error.
|
||||
|
||||
"To explore the asynchronity of the event raising, you can comment out the
|
||||
"following WAIT statement.
|
||||
WAIT UP TO 2 SECONDS.
|
||||
DATA(tmstmp_after_wait) = cl_abap_tstmp=>utclong2tstmp( utclong_current( ) ).
|
||||
out->write( |Timestamp (e.g. for comparing with the timestamps of the events raised): { tmstmp_after_wait }| ).
|
||||
out->write( |\n| ).
|
||||
|
||||
"The global class of the behavior pool contains a static attribute of type i.
|
||||
"The example is implemented as follows: When events are raised in the save_modified
|
||||
"method, this number is increased by 1 per event raised. The number represents
|
||||
"the expected events to be raised. It is used in the following example implementation.
|
||||
"As mentioned above, you can comment out the WAIT statement to potentially see
|
||||
"a different number here compared to the number of entries in the log table.
|
||||
out->write( |Number of expected events raised: { zbp_demo_abap_rap_ro_m_as=>num_raised_events }| ).
|
||||
out->write( |\n| ).
|
||||
|
||||
"Getting and displaying database table entries that were inserted
|
||||
"in the event handler method implementations to demonstrate that
|
||||
"events have been triggered.
|
||||
SELECT calc_result, crea_date_time
|
||||
FROM zdemo_abap_draft
|
||||
ORDER BY crea_date_time
|
||||
INTO TABLE @DATA(evt_log_entries).
|
||||
|
||||
out->write( |Entries in log table at this stage (after SELECT from database table): { lines( evt_log_entries ) }| ).
|
||||
out->write( |\n| ).
|
||||
|
||||
DATA(flag) = abap_false.
|
||||
IF evt_log_entries IS INITIAL.
|
||||
out->write( `There are no entries in the log table.` &&
|
||||
` Try and run the example again.` ).
|
||||
flag = abap_true.
|
||||
ELSEIF lines( evt_log_entries ) BETWEEN 1 AND zbp_demo_abap_rap_ro_m_as=>num_raised_events - 1.
|
||||
out->write( `Log database table entries created by the ` &&
|
||||
`raised events` )->write( `Note that not all expected log database table entries have been created yet by the ` &&
|
||||
`raised events`
|
||||
)->write( evt_log_entries ).
|
||||
flag = abap_true.
|
||||
ELSE.
|
||||
out->write( `Log database table entries created by the ` &&
|
||||
`raised events`
|
||||
)->write( evt_log_entries ).
|
||||
ENDIF.
|
||||
|
||||
"The following implementation is included for exploring the asynchronity in the self-contained example, if you
|
||||
"have commented out the WAIT statement above, or if not all expected entries are available in the database table
|
||||
"yet. This is just to give it some more time and select from the database table again.
|
||||
IF flag = abap_true.
|
||||
out->write( |\n| ).
|
||||
out->write( |******************************************************| ).
|
||||
out->write( |\n| ).
|
||||
out->write( |Out of { zbp_demo_abap_rap_ro_m_as=>num_raised_events } events that are expected to be raised in the example implementation, | &&
|
||||
|only { lines( evt_log_entries ) } events are available in the database table at this stage. So, waiting a bit more ...| ).
|
||||
out->write( |\n| ).
|
||||
|
||||
WAIT UP TO 1 SECONDS.
|
||||
|
||||
SELECT calc_result, crea_date_time
|
||||
FROM zdemo_abap_draft
|
||||
ORDER BY crea_date_time
|
||||
INTO TABLE @evt_log_entries.
|
||||
|
||||
IF lines( evt_log_entries ) = zbp_demo_abap_rap_ro_m_as=>num_raised_events.
|
||||
out->write( `Log database table entries created by the ` &&
|
||||
`raised events after waiting some more time`
|
||||
)->write( evt_log_entries ).
|
||||
ELSE.
|
||||
out->write( |Hmm... still not all events are available in the database table.| ).
|
||||
out->write( evt_log_entries ).
|
||||
ENDIF.
|
||||
ENDIF.
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD class_constructor.
|
||||
DELETE FROM zdemo_abap_tabca.
|
||||
DELETE FROM zdemo_abap_draft.
|
||||
CLEAR zbp_demo_abap_rap_ro_m_as=>num_raised_events.
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
||||
16
src/zcl_demo_abap_rap_m_as.clas.xml
Normal file
16
src/zcl_demo_abap_rap_m_as.clas.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
|
||||
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
|
||||
<asx:values>
|
||||
<VSEOCLASS>
|
||||
<CLSNAME>ZCL_DEMO_ABAP_RAP_M_AS</CLSNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>ABAP cheat sheet: Local consumption of RAP Business Events</DESCRIPT>
|
||||
<STATE>1</STATE>
|
||||
<CLSCCINCL>X</CLSCCINCL>
|
||||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>X</UNICODE>
|
||||
</VSEOCLASS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
6
src/zdemo_abap_abstract_ent.ddls.asddls
Normal file
6
src/zdemo_abap_abstract_ent.ddls.asddls
Normal file
@@ -0,0 +1,6 @@
|
||||
@EndUserText.label: 'Demo abstract entity'
|
||||
define abstract entity zdemo_abap_abstract_ent
|
||||
{
|
||||
col1: abap.char(25);
|
||||
col2: abap.char(25);
|
||||
}
|
||||
17
src/zdemo_abap_abstract_ent.ddls.baseinfo
Normal file
17
src/zdemo_abap_abstract_ent.ddls.baseinfo
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"BASEINFO":
|
||||
{
|
||||
"FROM":
|
||||
[],
|
||||
"ASSOCIATED":
|
||||
[],
|
||||
"BASE":
|
||||
[],
|
||||
"ANNO_REF":
|
||||
[],
|
||||
"SCALAR_FUNCTION":
|
||||
[],
|
||||
"VERSION":0,
|
||||
"ANNOREF_EVALUATION_ERROR":""
|
||||
}
|
||||
}
|
||||
13
src/zdemo_abap_abstract_ent.ddls.xml
Normal file
13
src/zdemo_abap_abstract_ent.ddls.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
|
||||
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
|
||||
<asx:values>
|
||||
<DDLS>
|
||||
<DDLNAME>ZDEMO_ABAP_ABSTRACT_ENT</DDLNAME>
|
||||
<DDLANGUAGE>E</DDLANGUAGE>
|
||||
<DDTEXT>Demo abstract entity</DDTEXT>
|
||||
<SOURCE_TYPE>A</SOURCE_TYPE>
|
||||
</DDLS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
21
src/zdemo_abap_rap_ro_m_as.bdef.asbdef
Normal file
21
src/zdemo_abap_rap_ro_m_as.bdef.asbdef
Normal file
@@ -0,0 +1,21 @@
|
||||
managed with additional save with full data
|
||||
implementation in class zbp_demo_abap_rap_ro_m_as unique;
|
||||
strict ( 2 );
|
||||
|
||||
define behavior for ZDEMO_ABAP_RAP_RO_M_AS alias root
|
||||
persistent table zdemo_abap_tabca
|
||||
lock master
|
||||
authorization master ( global )
|
||||
|
||||
{
|
||||
create;
|
||||
update;
|
||||
delete;
|
||||
internal action calc;
|
||||
event created;
|
||||
event updated parameter zdemo_abap_abstract_ent;
|
||||
event deleted parameter zdemo_abap_abstract_ent;
|
||||
field ( numbering : managed, readonly : update ) id;
|
||||
//determination det_save on save { field calc_result; }
|
||||
determination det_modify on modify { field num1, num2, arithm_op; }
|
||||
}
|
||||
14
src/zdemo_abap_rap_ro_m_as.ddls.asddls
Normal file
14
src/zdemo_abap_rap_ro_m_as.ddls.asddls
Normal file
@@ -0,0 +1,14 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
define root view entity ZDEMO_ABAP_RAP_RO_M_AS
|
||||
as select from zdemo_abap_tabca
|
||||
{
|
||||
key id,
|
||||
num1,
|
||||
arithm_op,
|
||||
num2,
|
||||
calc_result,
|
||||
@Semantics.systemDateTime.createdAt: true
|
||||
crea_date_time,
|
||||
@Semantics.systemDateTime.lastChangedAt: true
|
||||
lchg_date_time
|
||||
}
|
||||
19
src/zdemo_abap_rap_ro_m_as.ddls.baseinfo
Normal file
19
src/zdemo_abap_rap_ro_m_as.ddls.baseinfo
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"BASEINFO":
|
||||
{
|
||||
"FROM":
|
||||
[
|
||||
"ZDEMO_ABAP_TABCA"
|
||||
],
|
||||
"ASSOCIATED":
|
||||
[],
|
||||
"BASE":
|
||||
[],
|
||||
"ANNO_REF":
|
||||
[],
|
||||
"SCALAR_FUNCTION":
|
||||
[],
|
||||
"VERSION":0,
|
||||
"ANNOREF_EVALUATION_ERROR":""
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user