Bonjour à tous,
Dans mes pérégrinations au sein du framework SAP FPM dont je vous parlais dans l’article précédent, j’ai été confronté à une problématique relative à l’ordonnancement des UIBB et de la gestion des évènements.
J’ai pu résoudre ceci grâce à l’utilisation du FPM Application Controller, et je vais tenter ici d’expliciter tout ça.
La situation
Mon application FPM possède un certain nombre de UIBB. Des Forms, des Composite, des Tabbed, des List, etc. En soit, le problème n’est pas là, car c’est un peu l’essence même des applications FPM : afficher des blocs de données sur un même écran.
En plus de cela, j’ai quelques boutons dans l’en-tête de l’application, par exemple, un bouton – spécifique – pour sauvegarder la commande affichée en modification.
Qui dit sauvegarder, dit appliquer des modifications à la base de données et les commiter, bien entendu.
Comme pour toute interface utilisateur, il est nécessaire d’effectuer des contrôles sur les saisies avant de mettre à jour les tables, de créer les objets, etc. De cette façon on est sûr de la cohérence des données enregistrées. Bref, je ne vais pas faire un cours là-dessus.
Or donc, nous avons plusieurs UIBB, chacun avec ses données potentiellement modifiables par l’utilisateur.
Initialement, j’avais mon premier bloc UIBB avec sa feeder class, et j’avais inséré la gestion des boutons spécifiques dans la méthode process_event de cette classe. Par ailleurs, la feeder class de chacun des UIBB se chargeait elle-même d’effectuer les contrôles sur ses propres données.
Au début tout sembler fonctionner
Le problème
Là où le bât a blessé, ce fut lors d’un test. L’utilisateur est sur son écran de modification de commande. Il change une valeur dans une cellule, mettons, du quatrième bloc FPM et clique sur le bouton de sauvegarde. Attention, l’utilisateur ne fait rien de plus, c’est-à-dire, il n’appuie pas sur la touche « Entrée » du clavier après avoir saisi sa valeur. Ce détail est très important.
Résultat : la commande est enregistrée mais sans prendre en compte la saisie de l’utilisateur. Pourquoi ?
Le fait que l’utilisateur n’ait pas validé cette saisie avant de sauvegarder fait que le moteur FPM n’a pas déclenché d’évènement sur le UIBB concerné. Du coup, lors du déclenchement de la sauvegarde, dans le premier bloc, le moteur n’a pas la nouvelle valeur et sauvegarde sans celle-ci.
La solution sale
J’ai analysé la situation et le problème. Et ma première idée fut la suivante : si le moteur FPM au moment de la sauvegarde ne sait pas ce qu’il s’est passé dans les blocs plus bas, il suffit de mettre la gestion de l’évènement de sauvegarde non pas dans le premier bloc, mais dans le dernier. Ainsi, que l’utilisateur appuie sur « Entrée » ou non, le moteur FPM aura parcouru tous les blocs avant d’arriver au dernier et forcément la modification de l’utilisateur est visible au moment de l’évènement de sauvegarde, donc prise en compte.
Pourquoi c’est sale ?
C’est sale, parce que je n’ai pas la main sur l’ordre dans lequel les blocs UIBB sont traités. Jusqu’à présent, ils ont toujours été traités dans l’ordre de leur ordonnancement via la configuration de l’application, mais je n’ai aucune certitude là-dessus. Une deuxième raison est que si un nouveau UIBB devait être ajouté après le dernier, il faudrait déplacer mon code de l’actuel dernier vers le nouveau dernier. On imagine bien le gros risque d’oubli sur ce point, quand bien même j’avais mis un gros avertissement en commentaire dans mon code de la feeder class. Il suffit de ne pas le savoir et là, c’est le drame.
La solution propre
C’est ce que j’aurais voulu faire dès le début, mais sans savoir où et comment le mettre en place. Et c’est aussi celle qui est proposée par SAP pour, entre autres, résoudre exactement ce problème.
When steering the application as a whole, it is sometimes necessary for the application to participate in all FPM
events that happen during the entire lifetime of the application, with one arbitrary single component instance. This
is not possible, for example, with simple UIBBs since the methods provided by the Web Dynpro interface
IF_FPM_UI_BUILDING_BLOCK
only participate in the FPM event loop when the corresponding UIBBs are visible
at the time the event loop happens, or become visible after the current event loop has finished successfully.
Furthermore the UIBBs cannot make assumptions about the sequence in which they are called. Therefore, an
application controller is provided that closes this gap.
Comme le titre de cet article le laisse penser, on va justement utiliser le FPM Application Controller. Une fois déclaré à notre application FPM, il permet de contrôler et diriger l’application dans son entièreté.
Déclarer le FPM Application Controller
Deux solutions sont possibles, mais je ne parlerai que de celle que j’ai utilisée. Il suffit de fournir à notre application FPM un composant Web Dynpro qui implémente l’interface IF_FPM_APP_CONTROLLER (respectivement GAF ou OVP). Pour cela, il faut se rendre dans l’écran de configuration du composant principal de l’application, puis via le bouton « Options du Floorplan » sélectionner l’entrée « Options de l’unité de pilotage des applications ». Dans la popup qui s’ouvre, renseigner le nom du composant Web Dynpro.
Dans mon cas, c’était assez simple car je me repose sur un squelette standard dont le composant principal implémentait déjà l’interface susmentionnée. Je n’ai eu qu’à le déclarer.
Utilisation du FPM Application Controller
Comme dit juste au-dessus, mon FPM Application Controller est un objet standard. Pour vous ce sera peut-être un spécifique. Mais dans mon cas, j’ai été obligé de faire un enhancement.
J’ai donc créé un post-exit enhancement sur la méthode AFTER_PROCESS_EVENT.
Cette méthode est exécutée une fois que le process_event de la feeder class de tous les UIBB a été traité. De fait, le moteur FPM a pu prendre en compte toutes les modifications ayant eu lieu à l’écran et la sauvegarde peut se faire en toute sécurité, sans perte de données.
Une réponse à “FPM – Gestion globale d’évènements via le FPM Application Controller”
[…] utilisé, comme pour un article précédent, l’application controller. Comme son nom l’indique, il permet de contrôler globalement certains aspects de […]