Dans cet article, nous allons voir comment interagir avec les Business Objects créés via ABAP RAP. Pour cela, nous utilisons EML ( Entity Manipulation Language ) qui fait partie du langage ABAP, et permet d’acceder aux BO RAP.

Le code est disponible sur le Github de Abapeur

Dans première partie nous verrons :

  • READ : Lire les données d’une entité d’un Business Object
  • CREATE : Créer une entité d’un business Object
  • UPDATE : Modifier une entité d’un business Object
  • DELETE : Suppimer une entité d’un business Object

Dans la 2ème partie nous verrons des notions plus poussées : CREATE-BY-ASSOTIATION, ACTIONS, etc…

Pour notre exemple, nous allons utiliser le RAP BO de démo mis à disposition par SAP sur BTP, ABAP Environment : /DMO/I_Travel_M

Exemple 1 : READ

    DATA : lt_keys          TYPE TABLE FOR READ IMPORT /DMO/I_Travel_M.
    lt_keys = VALUE #( ( %tky-%key-travel_id = '00002772' ) ).
    READ ENTITY /DMO/I_Travel_M
    ALL FIELDS
    WITH CORRESPONDING #( lt_keys )
    RESULT data(lt_travel_data_r)
    FAILED DATA(lt_failed).

Nous venons lire les champs de Business Objects en précisant les champs clés (ici travel_id au sein de %tky). Il s’agit d’un des travel_id qu’on peut retrouver dans la table /dmo/travel_m :

De manière générale, Je conseille d’utiliser %tky dès que possible lorsque vous travaillez sur une instance d’un BO RAP car il contient tous les éléments nécessaire à l’identification unique d’une entité : %key mais aussi %pid (dans le cas de late numbering) et %is_draft (dans le cas de draft scenario).

Pour plus de détails, voir ici

En exécutant en debug on voit que les données sont récupérées :

On pourrait tout autant lire 2 lignes en un seul appel :

Exemple 2 : CREATE

    DATA lt_travel_new_data TYPE TABLE FOR CREATE /dmo/i_travel_m.
    lt_travel_new_data = VALUE #( ( %cid = '1'
                                    agency_id = '070049'
                                    customer_id = '000072'
                                    begin_date = cl_abap_context_info=>get_system_date( ) + 1
                                    end_date = cl_abap_context_info=>get_system_date( ) + 2
                                    overall_status = 'O'
                                    %control = VALUE #( agency_id = if_abap_behv=>mk-on
                                                        customer_id = if_abap_behv=>mk-on
                                                        begin_date = if_abap_behv=>mk-on
                                                        end_date = if_abap_behv=>mk-on
                                                        overall_status = if_abap_behv=>mk-on )
                                 )
                                 ( %cid = '2'
                                    agency_id = '070049'
                                    customer_id = '000072'
                                    begin_date = cl_abap_context_info=>get_system_date( ) + 1
                                    end_date = cl_abap_context_info=>get_system_date( ) + 2
                                    overall_status = 'O'
                                    %control = VALUE #( agency_id = if_abap_behv=>mk-on
                                                        customer_id = if_abap_behv=>mk-on
                                                        begin_date = if_abap_behv=>mk-on
                                                        end_date = if_abap_behv=>mk-on
                                                        overall_status = if_abap_behv=>mk-on )
                                 ) ).
    MODIFY ENTITY /dmo/i_travel_m
    CREATE FROM lt_travel_new_data
    FAILED DATA(lt_failed)
    REPORTED DATA(lt_reported)
    MAPPED DATA(lt_mapped).
    lt_travel_new_data = VALUE #( ( %cid = '1'
                                    agency_id = '070049'
                                    customer_id = '000072'
                                    begin_date = cl_abap_context_info=>get_system_date( ) + 1
                                    end_date = cl_abap_context_info=>get_system_date( ) + 2
                                    overall_status = 'O'
                                    %control = VALUE #( agency_id = if_abap_behv=>mk-on
                                                        customer_id = if_abap_behv=>mk-on
                                                        begin_date = if_abap_behv=>mk-on
                                                        end_date = if_abap_behv=>mk-on
                                                        overall_status = if_abap_behv=>mk-on )
                                 ) ).
    MODIFY ENTITY /dmo/i_travel_m
    CREATE FROM lt_travel_new_data
    FAILED lt_failed
    REPORTED lt_reported
    MAPPED lt_mapped.
    COMMIT ENTITIES
    RESPONSE OF /dmo/i_travel_m
    FAILED DATA(failed_commit)
    REPORTED DATA(reported_commit).

Dans cet exemple nous venons créer 3 nouvelles entités.

  • Nous précisons un %CID : Le %CID permet de relier la requête effectuée aux clés générées.

Typiquement, ici nous sommes dans le cas d’un « early numbering » : Le champs clé (travel_id) est déterminé automatiquement par le Business Object lors de la création. Afin de savoir quelle clé associée est crée, dans la structure de retour MAPPED, on retrouvera le lien entre le %CID envoyé dans la requête et la clé générée.

Imaginons que nous créions plusieurs entités en même temps, c’est nécessaire d’avoir le lien %CID + clés associées afin de savoir quelles valeurs sont a relier à quelles requêtes.

A noter :

1. Dans le cas d’un « late numbering », les clés ne sont crées que dans la phase de sauvegarde. Il n’est donc pas possible de retourner le lien %CIDs + clés. De plus le %CID n’est valable que dans la phase d’intéraction et ne sera donc plus disponible dans la phase de sauvegarde.

Pour cela, SAP a mis a disposition le %PID qui permet de créer une clé temporaire, valable lors de la phase de sauvegarde également. Ce %PID sera remplacé lors de la phase de sauvegarde par la vrai clé.

2. A la différence du %CID qui doit être unique dans la requête EML uniquement. Le %PID doit être unique pour l’instance (donc tant que l’entité n’a pas été sauvegardée. Typiquement, le %PID sera stocké également si le BO est en DRAFT)

3. Meme dans le cas ou nous ne sommes pas en « early numbering » ou en « late numbering », lorsque le Behavior Definition est definit en strict( 2 ), alors le %CID est obligatoire dans le statement EML pour appeler le CREATE ( et CREATE BY, UPDATE, DELETE, actions avec EXECUTE ). On pourrait penser que comme nous donnons les clés directement dans la requête, alors pas besoin de %CID. Mais cependant, cela permet de conserver les bonnes pratiques et de respecter les « implementation contract » : %CID obligatoire ainsi que tous les champs notés comme obligatoires dans le Behavior Definition à la création.

  • Nous précisons les champs que nous voulons dans lors de la création : agency_id, customer_id et begin_date, end_date
  • On précise les champs créés dans %control pour indiquer qu’il faut les prendre en compte dans la création

Dans cet exemple, je vous montre qu’on peut créer 2 entités avec le meme %CID, tant qu’ils ne sont pas dans le même statement EML

En debug :

  • On voit que les 2 premières entités sont correctement crées :
  • Puis la 3eme
  • Enfin, afin de terminer la phase d’interaction, on utilise COMMIT ENTITIES, qui va effectuer la phase de sauvegarde.

Exemple 3 : UPDATE

    DATA lt_travel_data TYPE TABLE FOR UPDATE /dmo/i_travel_m.
    lt_travel_data = VALUE #( ( %tky-%key-travel_id = '00002772'
                                description = 'Vacation'
                                %control-description = if_abap_behv=>mk-on ) ).
    MODIFY ENTITY /dmo/i_travel_m
    UPDATE FROM lt_travel_data
    FAILED DATA(lt_failed_u)
    REPORTED DATA(lt_reported_u).
    COMMIT ENTITIES
    RESPONSE OF /dmo/i_travel_m
    FAILED DATA(failed_commit)
    REPORTED DATA(reported_commit).

Ici on vient updater le travel_id 00002772 en ajoutant la description « Vacation »

On précise les champs updatés dans %control pour indiquer qu’il faut les prendre en compte dans l’update

Exemple 4 : CREATE et UPDATE

Dans cet exemple je vous montre comment créer et updater une entité qui n’a pas encore été sauvegardée (on crée, puis ensuite on update tout de suite sans passer par un COMMIT entre temps, donc la données créée n’est pas encore persistée).

  • Pour la création c’est identique à tout à l’heure
  • Pour l’update, nous utilisons %tky afin d’identifier l’entité a modifier. Ce %tky qui prend la valeur du %tky retourné dans la variable MAPPED par le CREATE précédent.
    DATA lt_travel_new_data TYPE TABLE FOR CREATE /dmo/i_travel_m.
    lt_travel_new_data = VALUE #( ( %cid = '1'
                                    agency_id = '070049'
                                    customer_id = '000072'
                                    begin_date = cl_abap_context_info=>get_system_date( ) + 1
                                    end_date = cl_abap_context_info=>get_system_date( ) + 2
                                    overall_status = 'O'
                                    %control = VALUE #( agency_id = if_abap_behv=>mk-on
                                                        customer_id = if_abap_behv=>mk-on
                                                        begin_date = if_abap_behv=>mk-on
                                                        end_date = if_abap_behv=>mk-on
                                                        overall_status = if_abap_behv=>mk-on )
                                 ) ).
    MODIFY ENTITY /dmo/i_travel_m
    CREATE FROM lt_travel_new_data
    FAILED DATA(lt_failed)
    REPORTED DATA(lt_reported)
    MAPPED DATA(lt_mapped).
    DATA(ls_mapped) = lt_mapped-travel[ 1 ].
    DATA lt_travel_data TYPE TABLE FOR UPDATE /dmo/i_travel_m.
    lt_travel_data = VALUE #( ( %tky = ls_mapped-%tky
                                description = 'Vacation'
                                %control-description = if_abap_behv=>mk-on ) ).
    MODIFY ENTITY /dmo/i_travel_m
    UPDATE FROM lt_travel_data
    FAILED DATA(lt_failed_u)
    REPORTED DATA(lt_reported_u).
    COMMIT ENTITIES
    RESPONSE OF /dmo/i_travel_m
    FAILED DATA(failed_commit)
    REPORTED DATA(reported_commit).

Exemple 5 : DELETE

    DATA : lt_keys          TYPE TABLE FOR DELETE /DMO/I_Travel_M.
    lt_keys = VALUE #( ( %tky-%key-travel_id = '00002772' )
                       ( %tky-%key-travel_id = '00002815' ) ).
    MODIFY ENTITY /DMO/I_Travel_M
    DELETE FROM lt_keys
    FAILED DATA(failed)
    REPORTED DATA(reported).

Ici, on vient préciser les clés des entités a suprimer et effectuer la suppression.

Conclusion

Vous savez desormais utiliser un RAP BO en ABAP en utilisant l’EML. Dans la pertie 2 nous rentrerons plus en profondeur sur d’autres possibilités en EML.