Benutzerdefinierte Logik hinzufügen

Objective

After completing this lesson, you will be able to implementieren Sie programmatische Validierungen mithilfe von .fore-Event-Handlern.

Kundeneigene Service-Implementierungen

Da die meisten Standardaufgaben und -anwendungsfälle von generischen Service-Providern abgedeckt werden, wird die Notwendigkeit, Serviceimplementierungscode hinzuzufügen, erheblich reduziert und verkleinert.

Die verbleibenden Fälle reduzieren sich auf echte benutzerdefinierte Logik, die für Ihre Domäne und Anwendung spezifisch ist, z.B. domänenspezifische programmatische Validierungen.

Programmieren wir beispielsweise eine Validierung, die sicherstellt, dass das verstrichene Geburtsdatum vor dem Todesdatum liegt, wenn ein neuer Autor über den AdminService angelegt wird.

Die einfachste Möglichkeit, benutzerdefinierte Dienstimplementierungen hinzuzufügen, besteht darin, einfach eine gleichnamige .js-Datei neben der .cds-Datei zu platzieren, die die entsprechende Dienstdefinition enthält. Das heißt, in unserem Fall legen wir eine Datei namens admin-service.js im Ordner srv unseres Projekts ab, da dieser Ordner auch die Datei admin-service.cds enthält, die zur Definition des AdminService verwendet wird (siehe folgende Abbildung).

Notiz

Alternativ können Sie die Service-Definition auch in der .cds-Datei mit der Annotation @impl annotieren. Sie verwenden diese Annotation, um explizit auf eine andere .js-Datei zu verweisen, die die Service-Implementierung enthalten sollte.

Es gibt verschiedene Möglichkeiten, die erforderliche benutzerdefinierte Logik in der .js-Datei zu implementieren. Die häufigste Methode besteht darin, eine Unterklasse von cds.ApplicationService zu verwenden, um von generischen, sofort einsatzbereiten Implementierungen zu profitieren. Dies liegt daran, dass die Klasse cds.ApplicationService die Standard-Service-Provider-Implementierung ist, die die bereits besprochenen generischen Provider zu einer Service-Definition hinzufügt.

Um eine Unterklasse von cds.ApplicationService anzulegen, ordnen wir zuerst das Modul @sap/cds der Konstante cds in unserem Quelltext zu (Zeile 1). Das Modul @sap/cds ist das CDS-Fassadenobjekt, das Zugriff auf alle CAP-Node.js-APIs bietet.

Anschließend legen wir in den Zeilen 4 bis 6 eine Unterklasse von cds.ApplicationService an, in der wir später unsere benutzerdefinierte Logik implementieren werden. Der Name der Unterklasse ist beliebig. Wir nennen es hier wie unser Service-Interface, d.h. AdminService.

In Zeile 9 stellen wir die AdminService-Klasse für den Import in andere Module bereit. Dies ist in Node.js üblich, um den Quelltext zu strukturieren.

Notiz

Wenn Sie nun die Anwendung starten, indem Sie im Terminal cds watch eingeben, wird die hinzugefügte Service-Implementierungsdatei im Protokoll über eine Ausgabe ähnlich der folgenden angezeigt:

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

Event-Handler

Kundeneigene Service-Implementierungen werden mit Hilfe von kundeneigenen Ereignisbehandlern durchgeführt, wobei zwischen verschiedenen Arten von Behandlern unterschieden wird.

Sehen Sie sich das Video an, um einen Überblick über die verschiedenen Event-Handler zu erhalten.

Registrierung von .before-Event-Handlern

Für die Validierung, die wir implementieren möchten, benötigen wir einen Before-Handler, der für CREATE- und UPDATE-Operationen auf der Entität Autoren registriert sein sollte.

Um benutzerdefinierte Ereignisbehandler zu registrieren, überschreiben Sie die geerbte init() Methode in der angelegten Implementierungsklasse (siehe folgende Abbildung). Vergessen Sie nicht, super.init() in der Implementierung aufzurufen, damit Unterklassen ihre Behandler registrieren können.

Um einen Before-Handler in der Methode init() zu registrieren, rufen Sie die geerbte Methode before() über this.before()auf. Dazu müssen Sie die folgende Schnittstelle bereitstellen. Eine detaillierte Beschreibung der einzelnen Parameter finden Sie in der CAP-Dokumentation:

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

Im gezeigten Beispiel ist die benannte Funktion this.validateLifeData für CREATE - und UPDATE -Operationen auf der Authors -Entität registriert. Die Implementierung dieser Funktion wird später besprochen.

Die Entität(en), für die die Registrierung erfolgen soll, kann als String an die Methode before() übergeben werden. Es wird jedoch empfohlen, stattdessen CSN-Definitionen zu übergeben. Die CSN-Definitionen der Entitäten, die über den Service bereitgestellt werden, werden bequem über die Eigenschaft this.entities bereitgestellt.

Im gezeigten Beispiel wird die erforderliche CSN-Definition für die Entität Autoren der Konstante Autoren über eine destrukturierende Zuordnung zugeordnet.

Notiz

Die Syntax für die Destrukturierung der Zuordnung ist JavaScript-Standard. Es handelt sich um einen JavaScript-Ausdruck, der es ermöglicht, Werte aus Arrays oder Eigenschaften aus Objekten in verschiedene Variablen zu entpacken.

Validierung eingehender Daten

Sehen wir uns abschließend an, wie die Funktion validateLifeData, die als Before-Handler registriert wurde, in der AdminService-Klasse implementiert werden kann.

Bevor Behandler in der Regel ein einzelnes Argument erhalten, eine Instanz von cds.Request. Diese Instanz stellt Eigenschaften und Methoden zur Verfügung, mit denen der Behandler implementiert werden kann. Im Beispiel haben wir das Argument req genannt (siehe folgende Abbildung).

Bei CREATE- und UPDATE-Requests, um die es hier geht, enthält die Eigenschaft data des Schnittstellenparameters den HTTP-Body des Requests. Wir verwenden eine destrukturierende Zuordnung, um die übergebenen Werte aus dem HTTP-Body den Konstanten dateOfBirth und dateOfDeath zuzuordnen.

Liegt das Sterbedatum vor dem Geburtsdatum, geben wir über die Methode req.error() eine entsprechende Fehlermeldung aus.

Notiz

Die Methode req.error() sammelt alle Fehler in der Eigenschaft req.errors, sodass sie auf allen UIs gleichzeitig angezeigt werden können. Wenn nach der Vorphase req.errors vorhanden sind, wird die Request-Verarbeitung mit einer entsprechenden Fehlerantwort abgebrochen, die an den Client zurückgegeben wird.

Hinweis

Das an die Methode req.error() übergebene Literal wird mit Backtick-Zeichen (`) abgegrenzt. Solche Template-Literale ermöglichen die Einbettung von Variablenwerten in einen String mit der Syntax ${name_of_the_variable}.

Demonstration und Übung: Bereitstellen eines .Before-Event-Handlers

Notiz

Führen Sie als Übung die Schritt-für-Schritt-Anleitung in der folgenden Demonstration selbst im SAP Business Application Studio durch.

Verwenden Sie als Ausgangspunkt für die Übung das Ergebnis der vorherigen Übung „Einen Service basierend auf denormalisierten Sichten definieren", wenn Sie sie erfolgreich abgeschlossen haben. Alternativ können Sie auch den Branch 10_denormalized_views aus dem folgenden GitHub-Repository als Ausgangspunkt verwenden:

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

Die vollständige Implementierung der Simulation finden Sie im Branch 11_.before_event_handler des GitHub-Repositorys.

Detaillierte Informationen zum Inhalt des Repositorys und dessen Verwendung finden Sie hier.

Sehen Sie sich das Video an, um zu sehen, wie Sie einen .Before-Event-Handler bereitstellen.