Après avoir travaillé sur plusieurs projets SAP, j’ai remarqué une tendance récurrente : une multitude de projets SEGW remplis de fonction imports qui sont généralement mal utilisés ou inutiles. Fort de mon expérience — et après avoir étudié la documentation SAP — j’ai décidé d’écrire ce blog afin de faire la lumière sur les fonction imports. J’expliquerai ce qu’ils sont, à quoi ils servent, quand les utiliser et quand il vaut mieux les éviter. Je le ferai non seulement pour les projets SAP SEGW, mais aussi pour leurs équivalents dans les frameworks plus récents que sont SAP RAP et CAP — car je m’investis activement dans ces approches de développement modernes et je travaille sur des projets métiers qui les exploitent.
Pour rendre cela plus concret, je présenterai un exemple pratique, que j’ai mis à disposition sur GitHub.
Éclaircissons cette confusion ensemble. Alors, attrapez votre café et plongeons dans le sujet !
Contexte SAP SEGW
Une fonction imports dans OData est un moyen de définir et d’appeler des opérations personnalisées dans un service, qui vont au-delà des actions standards de gestion des données — comme la création, la lecture, la mise à jour ou la suppression d’enregistrements (CRUD). Ces actions standard sont généralement prises en charge via les méthodes HTTP POST, GET, PUT/MERGE et DELETE
Cependant, si vous devez effectuer une tâche plus spécifique qui ne rentre pas parfaitement dans les opérations CRUD classiques, vous pouvez créer un fonction imports dans votre modèle de données à l’aide de Service Builder. Ces opérations personnalisées peuvent ensuite être déclenchées via les méthodes HTTP GET ou POST.
Mais d’abord, un petit mot de prudence : ces fonction imports spécifiques ne doivent être utilisés que pour des actions impossibles à réaliser avec les opérations CRUD traditionnelles. Si la tâche peut être accomplie via une création, lecture, mise à jour ou suppression standard, alors une fonction imports n’est pas nécessaire.
Voyons un exemple pour mieux comprendre.
Exemple : système de gestion des vols avec opérations CRUD et personnalisées
Opérations CRUD de base :
Ces opérations couvrent les besoins fondamentaux de gestion des données pour les enregistrements de vols :
- Créer : Ajouter un nouveau vol (par ex. : POST /flight avec origine, destination, heure de départ, arrivée…).
- Lire : Récupérer un vol existant (par ex. : GET /flight/{id}).
- Mettre à jour : Modifier un vol (par ex. : PUT /flight/{id} pour ajuster l’heure de départ).
- Supprimer : Supprimer un vol annulé (par ex. : DELETE /flight/{id}).
Opérations personnalisées :
Il s’agit d’opérations spécifiques au métier, qui vont au-delà du CRUD standard :
- Imprimer les détails : Générer et imprimer des informations complètes sur le vol (par ex. : planning, appareil, disposition des sièges).
- Générer un rapport : Créer des rapports opérationnels ou statistiques sur les vols dans une plage de dates donnée.
- …
Les opérations personnalisées sont séparées du CRUD car elles encapsulent des comportements propres au domaine métier, qui ne peuvent pas être gérés simplement par de la manipulation de données.
Alors que les opérations CRUD se concentrent sur la création, la lecture, la mise à jour ou la suppression d’enregistrements, les actions personnalisées réalisent souvent des calculs, déclenchent des workflows ou appliquent des règles métier sur plusieurs entités.
Cette distinction permet une architecture plus claire et plus facile à maintenir — où le CRUD gère la persistance des données de base, tandis que les opérations personnalisées prennent en charge la logique métier plus fine et spécifique à l’application.
Exemple d’implémentation
Voici un exemple d’implémentation de l’appel à une fonction imports défini dans SEGW.
Côté front-end, une fonction imports est déclenché via une requête OData en utilisant callFunction(), par exemple :
/sap/opu/odata/SERVICE_NAME/FunctionImportName(…)
Côté back-end, cela est géré en redéfinissant la méthode EXECUTE_ACTION dans la classe *_DPC_EXT.
Dans cette méthode, le paramètre iv_action_name permet d’identifier la fonction spécifique appelée. Les paramètres d’entrée sont accessibles via la table it_parameter, et la logique métier correspondante est alors implémentée en conséquence.
Code front-end :
let oModel = this.getView().getModel();
let mParameters = {
FlightID: "12345"
};
oModel.callFunction("/PrintFlightDetails", {
method: "POST",
urlParameters: mParameters,
success: function(oData, response) {
MessageToast.show(oData.Message);
},
error: function(oError) {
MessageToast.show("Error printing flight details");
}
});
Code back-end :
(En supposant que nous avons préalablement défini la fonction imports dans le projet SEGW, ainsi qu’une classe ABAP orientée objet pour gérer l’objet métier Flight)
METHOD execute_action.
" Check if the action name is 'PrintFlightDetails'
IF iv_action_name = 'PrintFlightDetails'.
" Retrieve input parameter
READ TABLE it_parameter INTO DATA(ls_parameter) WITH KEY name = 'FlightID'.
IF sy-subrc = 0.
DATA(lv_flightid) = ls_parameter-value.
ELSE.
" Manage error
ENDIF.
" Instantiate the flight manager class
DATA(lo_flight) = NEW zcl_flight( lv_flightid ).
" Call the method to update the flight status
DATA(lv_message) = lo_flight->print_flight_details( ).
...
ENDIF.
ENDMETHOD.
Conclusion
Les fonction imports sont un outil puissant, mais comme tout outil, ils doivent être utilisés avec discernement. Dans SEGW, il est préférable de les réserver aux opérations qui ne s’intègrent pas naturellement dans le CRUD. Un mauvais usage peut entraîner des services surchargés, peu clairs, et inutilement complexes.
Dans la prochaine partie de cette série, j’explorerai comment des cas d’usage similaires sont gérés dans RAP et CAP — avec un projet GitHub pour illustrer tout cela en pratique.