Ajout d'une logique personnalisée

Objective

After completing this lesson, you will be able to implémenter des validations programmatiques à l'aide des gestionnaires d'événements .before

Implémentations de service personnalisées

Comme la plupart des tâches et des cas d'utilisation standard sont couverts par des fournisseurs de services génériques, la nécessité d'ajouter du code d'implémentation de service est considérablement réduite et réduite.

Les cas restants se réduisent à une logique personnalisée réelle, spécifique à votre domaine et à votre application, comme les validations programmatiques spécifiques au domaine.

À titre d'exemple, programmons une validation qui garantit que la date de naissance passée est antérieure à la date de décès passée lors de la création d'un nouvel auteur via AdminService.

Le moyen le plus simple d'ajouter des implémentations de service personnalisées est de placer un fichier .js tout aussi nommé à côté du fichier .cds contenant la définition de service correspondante. C'est-à-dire que dans notre cas, nous plaçons un fichier nommé admin-service.js dans le dossier srv de notre projet, car ce dossier contient également le fichier admin-service.cds, qui est utilisé pour définir le AdminService (voir la figure suivante).

Remarque

Vous pouvez également annoter la définition de service dans le fichier .cds avec l'annotation @impl . Vous utilisez cette annotation pour faire explicitement référence à un autre fichier .js qui doit contenir l'implémentation de service.

Il existe différentes façons d'implémenter la logique personnalisée requise dans le fichier .js. La manière la plus courante est d'utiliser une sous-classe de cds.ApplicationService pour bénéficier d'implémentations génériques prêtes à l'emploi. En effet, la classe cds.ApplicationService est l'implémentation du fournisseur de services par défaut, qui ajoute les fournisseurs génériques déjà abordés à une définition de service.

Pour créer une sous-classe de cds.ApplicationService, nous affectons d'abord le module @sap/cds aux cds constantes dans notre code (ligne 1). Le module @sap/cds est l'objet de façade cds qui permet d'accéder à toutes les API CAP Node.js.

Nous créons ensuite une sous-classe de cds.ApplicationService dans les lignes 4 à 6, dans laquelle nous implémenterons plus tard notre logique personnalisée. Le nom de la sous-classe est arbitraire. Nous l'appelons ici comme notre interface de service, i.e. AdminService.

À la ligne 9, nous rendons la classe AdminService disponible pour l'importation dans d'autres modules. C'est une pratique courante dans Node.js pour structurer le code.

Remarque

Si vous lancez maintenant l'application en saisissant cds watch dans le terminal, le fichier d'implémentation de service ajouté est affiché dans le journal via une sortie similaire à ce qui suit :

Code Snippet
1
[cds] - serving AdminService { path: '/admin', impl: 'srv/admin-service.js' }

Gestionnaires d'événements

Les implémentations de service personnalisées sont exécutées à l'aide de gestionnaires d'événements personnalisés, où une distinction est faite entre les différents types de gestionnaires.

Regardez la vidéo pour obtenir une synthèse des différents gestionnaires d'événements.

Enregistrement du fichier .before des gestionnaires d'événements

Pour la validation que nous voulons implémenter, nous avons besoin d'un avant gestionnaire qui doit être enregistré pour les opérations CREATE et UPDATE sur l'entité Auteurs.

Pour enregistrer des gestionnaires d'événements personnalisés, écrasez la méthode init() héritée dans la classe d'implémentation créée (voir figure suivante). N'oubliez pas d'appeler super.init() dans l'implémentation pour permettre aux sous-classes d'enregistrer leurs gestionnaires.

Pour enregistrer un before handler dans la méthode init() , appelez la méthode before() héritée via this.before(). Pour ce faire, vous devez fournir l'interface suivante. Vous trouverez une description détaillée des différents paramètres dans la documentation de la PAC :

Code Snippet
12345
function before ( event : string | string[] | '*', entity? : CSN definition | CSN definition[] | string | string[] | '*', handler : function )

Dans l'exemple illustré, la fonction nommée this.validateLifeData est enregistrée pour les opérations CREATE et UPDATE sur l'entité Authors. Nous discuterons plus tard de l'implémentation de cette fonction.

La ou les entités pour lesquelles l'enregistrement doit avoir lieu peuvent être transmises à la méthode before() sous forme de chaîne. Cependant, il est recommandé de transmettre les définitions CSN ici à la place. Les définitions CSN des entités qui sont exposées via le service sont facilement disponibles via la propriété this.entities .

Dans l'exemple illustré, la définition CSN requise pour l'entité Auteurs est affectée à la constante Auteurs via une affectation de destruction.

Remarque

La syntaxe d'affectation de déstructuration est JavaScript standard. Il s'agit d'une expression JavaScript qui permet de décompresser des valeurs de tableaux, ou des propriétés d'objets, dans des variables distinctes.

Validation des données entrantes

Enfin, examinons comment la fonction validateLifeData qui a été enregistrée en tant que gestionnaire peut être implémentée sur la classe AdminService.

Avant que les gestionnaires reçoivent généralement un seul argument, une instance de cds.Request. Cette instance fournit des propriétés et des méthodes qui peuvent être utilisées pour implémenter le gestionnaire. Dans l'exemple, nous avons nommé l'argument req (voir la figure suivante).

Pour les requêtes CREATE et UPDATE, qui nous concernent ici, la propriété de données du paramètre d'interface contient le corps HTTP de la requête. Nous utilisons une affectation de destruction pour affecter les valeurs transmises du corps HTTP aux constantes dateOfBirth et dateOfDeath.

Si la date de décès est antérieure à la date de naissance, nous émettons un message d'erreur correspondant via la méthode req.error() .

Remarque

La méthode req.error() collecte toutes les défaillances dans la propriété req.errors, ce qui permet de les afficher sur les IU en une seule fois. S'il y a req.errors après la phase précédente, le traitement de la demande est interrompu avec une réponse d'erreur correspondante renvoyée au client.

Astuce

Le littéral passé à la méthode req.error() est délimité par des caractères backtick (`). Ces littéraux de modèle permettent d'incorporer des valeurs de variables dans une chaîne à l'aide de la syntaxe ${name_of_the_variable}.

Démonstration et exercice : fournir un .before Event Handler

Remarque

Dans l'exercice, suivez les instructions étape par étape de la démonstration suivante dans SAP Business Application Studio.

Comme point de départ de l'exercice, utilisez le résultat de l'exercice précédent Définition d'un service basé sur des vues dénormalisées si vous avez terminé l'exercice avec succès. Vous pouvez également utiliser la branche 10_denormalized_views du référentiel GitHub suivant comme point de départ :

https://github.com/SAP-samples/cap-development-learning-journey

L'implémentation complète de la simulation se trouve dans la branche 11_.before _event_handler du référentiel GitHub.

Vous trouverez ici des informations détaillées sur le contenu du référentiel et son utilisation.

Regardez la vidéo pour voir comment fournir un gestionnaire d'événements .before.