Dans cet article nous allons nous pencher en détails sur le « Background Process Framework », également appelé bgPF. A quoi ça sert ? Quel est son intêret en ABAP Cloud et dans les applications RAP ?

Puis nous verrons un exemple concret que j’ai préparé.

Tout d’abord, je vous incite à aller lire mon article Application RAP avec BAPI – Objectif Clean Core – section « ABAP RAP, dans le contexte d’ABAP CLOUD » si vous souhaitez comprendre un peu mieux les concepts en ABAP Cloud et notamment les concepts de LUW et Controlled LUW (comment et quand les données doivent être sauvegardées dans le système).

Prérequis techniques : BTP, ABAP environment (via Trial BTP par exemple, ce qui est fait ici), S/4 Hana Cloud, S/4 Hana On Premise / Private Cloud releases supérieures ou égales à 2023.

bgPF c’est quoi ?

Pour faire simple, Le bgPF offre la fonctionnalité d’exécuter des étapes de traitement en arrière-plan, de manière fiable pour les différentes applications qui sont développées. Il s’agit d’une fonctionnalité simple et facile à utiliser pour exécuter de manière asynchrone et fiable des méthodes ABAP qui prennent du temps.

Également, l’utilisation de bgPF s’avère utile si vous devez déclencher une fonctionnalité dans une session différente de celle en cours, par exemple parce que la fonctionnalité que vous souhaitez appeler effectue un commit de base de données alors que vous êtes encore dans la phase d’interaction (cf. Mon article cité plus haut si besoin de plus de détails sur les différentes phases en ABAP Cloud).

Pour terminer, on peut également considéré bgPF comme le successeur des tRFC et qRFC.

Dans ce shema nous pouvons voir le fonctionnement avec bgPF :

  1. L’application crée une instance bgPF ( voir plus bas dans l’exemple comment faire )
  2. l’execution du bgPF est mis « en attente »
  3. Une fois le COMMIT dans l’application effectuée, le(s) bgPF s’execute(nt).

La documentation technique bgPF : https://help.sap.com/docs/abap-cloud/abap-concepts/background-processing-framework

La documentation technique controlled LUW : https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw

L’introduction au bgPF dont j’ai repris les informations : https://community.sap.com/t5/technology-blogs-by-sap/introducing-the-background-processing-framework/ba-p/13579056

Cas de test

Pour faire cet exemple, j’avais le choix de prendre :

  • Soit le cas d’un process qui doit être exécuté en arrière plan car consommateur en ressource et en temps
  • Soit le cas où l’utilisation du bgPF est nécessaire pour conserver le « transactional consistency ». Pour rappel, le « transational consistency » est le fait de respecter les règles de LUW au sein du Cloud en ABAP, soit :

1/ Une phase d’interaction ou toutes les données modifiées, créées, supprimées sont placées dans un buffer et validées

2/ Une phase de sauvegarde ou plus aucune erreur n’est censée arriver et où la donnée est stockée de manière persistante dans la base de données.

Cette vidéo (à partir de la minute 41, explique très bien le concept) :

Comme il y a déjà des exemples sur internet sur l’utilisation du bgPF pour le premier cas, nous nous pencherons sur le 2ème cas : bgPF dans le cadre du « transactional consistency ».

Description de l’exemple

Ici, nous allons donc créer une application RAP, qui doit appeler une API POST (donc créer de la donnée) dans un système externe lors de la création d’une nouvelle ligne (pas dans le cas d’une modification ou suppression, seulement dans le cas d’une création).

A noter qu’ici je vais utiliser un appel API POST factice qui ne fait que renvoyer un ID sans rien faire de spécial mais c’est seulement à titre d’exemple (API utilisée : https://www.toptal.com/developers/postbin/ )

Ce cas fonctionne pour tous les cas où il y a connexion distante (RFC, API, etc…) dans le but de modifier, supprimer, créer de la donnée.

Voici les problématiques :

1/ En respectant les règles stricts du « controlled LUW » en créant une application RAP (identifié par le statement « strict(2) » lors du behavior implementation, ce que je conseille toujours, nous y reviendrons plus bas), il est impossible d’appeler une API via un client HTTP dans la phase de sauvegarde.

Pourquoi ? Car l’établissement d’une connexion HTTP effectue un « implicit database commit ». Hors c’est interdit car si vous aviez commencé à écrire des informations dans la base de données, ce qui est le but de la phase de sauvegarde, alors les données seront sauvegardées dans la base de donnée alors même que nous ne sommes pas à l’abri d’une quelconque erreur plus tard dans le processus de sauvegarde.

2/ Techniquement, nous pourrions appeler cette API POST dans la phase d’interaction. D’ailleurs, c’est ce qui est conseillé de faire pour obtenir de la donnée (faire un GET).
En effet, comme il est interdit d’écrire de la donnée dans la phase d’interaction, ce n’est pas grave s’il y a des « implicit database commit » puisque aucune donnée ne sera donc sauvegardée dans la base de données.
HORS ici, il ne s’agit pas seulement de lire, mais aussi d’écrire de la donnée. Cela ne fait donc pas sens de venir créer de la donnée dans la phase d’interaction : Et s’il y avait une erreur lors d’une validation de la donnée par exemple ? Alors nous n’arriverions jamais la phase de sauvegarde et nous aurions déjà écris la données dans le système distant sans finir totalement le processus.

La solution : Dans ce cas là il faut donc créer un processus qui sera appelé dans une autre session, lors de la phase de sauvegarde, ce qui permettra de ne pas créer de « database commit ». Nous utiliserons donc le bgPF lors de la phase de sauvegarde.

Implémentation du cas de test

1/ Création d’une application RAP basique

Ici j’ai créé une application RAP basique de toute pièce, en passant d’une table Z à la création des CDS et des Behaviors

Je ne rentre pas dans le détail de cette création car il suffit de suivre ce tuto simple : https://developers.sap.com/group.abap-build-fiori-element-rap.html

Voici les objets générés, qui permettent de créer une application de gestion des voyages.

Par contre nous devrons modifier par la suite cette application pour ajouter l’appelle du bgPF, j’y reviendrai.

2/ Création de la classe bgPF

Il y a 2 choix :

  • Soit une interface qui permet de respecter les règles du « transactional consistency » au sein du bgPF => if_bgmc_op_single
  • Soit une interface « uncontrolled » => if_bgmc_op_single_tx_uncontr

Comme cette classe n’aura comme seul but d’appeler une API POST, je vais utiliser l’interface if_bgmc_op_single_tx_uncontr

CLASS zbgpf DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
  INTERFACES if_bgmc_op_single_tx_uncontr.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS zbgpf IMPLEMENTATION.

  METHOD if_bgmc_op_single_tx_uncontr~execute.

    TRY.
        "DUMMY HTTP POST REQUEST
        DATA(dest) = cl_http_destination_provider=>create_by_url( 'https://www.toptal.com/developers/postbin/1715537134683-0620718607679' ).
        DATA(client) = cl_web_http_client_manager=>create_by_http_destination( dest ).
        DATA(req) = client->get_http_request(  ).
        DATA(post) = client->execute( if_web_http_client=>post )->get_text(  ).
        client->close(  ).
      CATCH cx_root INTO DATA(error). "Catch all exceptions
    ENDTRY.

  ENDMETHOD.

ENDCLASS.

Dans la méthode if_bgmc_op_single_tx_uncontr~execute, j’ai écris la création du client HTTP suivi de l’appel API POST qui doit être effectué en arrière plan.

3/ Modifier le behavior definition pour passer la phase de sauvegarde en « unmanaged save » et ainsi gérer en autonomie la phase de sauvegarde.

Suppression du statement « persistent table » et création du « unmanaged save », ce qui permet de générer ensuite une méthode pour gérer soit même la gestion de la sauvegarde (on voit d’ailleurs ici que nous sommes bien en mode strict(2) ) :

4/ Implémentation de la méthode de sauvegarde

  METHOD save_modified.

DATA: ls_ZTEST_TABLE_CRT TYPE ZTEST_TABLE_CRT.

1/ On boucle sur les données modifiées pour modifier les lignes de la table
LOOP AT update-zr_test_table_crt INTO data(ls_update).
ls_ZTEST_TABLE_CRT = CORRESPONDING #( ls_update MAPPING FROM
ENTITY ).
MODIFY ZTEST_TABLE_CRT FROM @ls_ZTEST_TABLE_CRT.
ENDLOOP.

2/ On boucle sur les données supprimées pour supprimer les lignes de la table
LOOP AT delete-zr_test_table_crt INTO data(ls_delete).
ls_ZTEST_TABLE_CRT = CORRESPONDING #( ls_delete MAPPING FROM
ENTITY ).
DELETE ZTEST_TABLE_CRT FROM @ls_ZTEST_TABLE_CRT.
ENDLOOP.

3/ On boucle sur les données à créer ET on appelle le bgPF créé plus haut
LOOP AT create-zr_test_table_crt INTO data(ls_create).
ls_ZTEST_TABLE_CRT = CORRESPONDING #( ls_create MAPPING FROM
ENTITY ).
MODIFY ZTEST_TABLE_CRT FROM @ls_ZTEST_TABLE_CRT.
* On instancie la classe pour le bgPF
    DATA(new) = NEW zbgpf(  ).
    DATA background_process TYPE REF TO if_bgmc_process_single_op.
    TRY.
* On crée le nouveau process qui devra être lancé en arrière plan
        background_process = cl_bgmc_process_factory=>get_default(  )->create(  ).
* On appelle l'opération qui devra être executée
        background_process->set_operation_tx_uncontrolled( new ).
* On sauvegarde pour exécution après COMMIT.
        background_process->save_for_execution(  ).
* COMMIT WORK. "Pas nécessaire dans le cas d'une application RAP car le framework le gère.
      CATCH cx_bgmc INTO DATA(exception).
    ENDTRY.
ENDLOOP.

  ENDMETHOD.

Ici comme nous somme dans une application RAP, il n’y a pas besoin d’avoir de COMMIT explicit puisque tout est géré par le framework RAP.

Et voilà, cette application RAP permet d’appeler une API POST en background lors de la phase de sauvegarde. Ceci permet de respecter le « transactional consistency » en ABAP Cloud.

Debug

J’ai mis un point d’arrêt dans la phase de sauvegarde pour voir ce qu’il s’y passe.

Je lance l’application en preview et crée une nouvelle entrée :

Lorsque je sauvegarde la création, j’arrive bien dans la méthode de sauvegarde préalablement créée :

Comme il n’y a pas d’update ou de suppression mais seulement une création, on arrive directement au traitement de l’instance nouvellement créée dans le buffer :

Et comme vu plus haut, ici ce passe la création et la mise en file d’attente du process d’arrière plan.

On voit d’ailleurs que le bgPF n’a pas été encore appelé, même en fin de méthode, puisqu’il n’y a pas encore eu le COMMIT :

Une fois le COMMIT atteint lors du processus du framework RAP, on arrive bien au bgPF :

Comme expliqué plus haut ici il s’agit juste d’un appel API POST de test qui renvoi un ID quelconque pour indiqué que l’appel c’est correctement passé, mais ça aurait pu être par exemple la création de la ligne créée dans l’application Fiori dans un système distant :

On retourne sur l’application Fiori et on voit la nouvelle ligne bien créée

Conclusion

Vous savez maintenant à quoi sert le bgPF, comment l’utiliser et quels sont les différents cas d’usage.

A noté qu’il est important de mettre en place un système de monitoring afin de valider que tout c’est correctement déroulé lors de l’exécution en arrière plan. SAP propose des solutions standards pour cela.

Repository Github : https://github.com/Abapeur/bgPF