Semantischen Schlüssel prüfen

Im ABAP-RESTful-Anwendungsprogrammiermodell setzt sich der Schlüssel einer Datenbanktabelle häufig aus dem Mandantenfeld und einem UUID-Feld zusammen, dessen Wert automatisch von der Laufzeit vergeben wird, wenn Sie eine neue Instanz des Business-Objekts anlegen. Diese Feldkombination ist ausreichend, um sicherzustellen, dass das System jeden Datensatz in der Tabelle eindeutig identifizieren kann. Neben diesem technischen Schlüssel hat unser Objekt jedoch auch einen semantischen Schlüssel - in diesem Fall die Kombination aus Fluggesellschaft und Flugnummer, die auch gemäß der Business-Logik eindeutig sein muss. Um die Eindeutigkeit dieser Feldkombination zu gewährleisten, müssen Sie eine eigene Prüfung in Form einer Validierung implementieren.
Sie deklarieren Validierungen in der Verhaltensdefinition der CDS-View-Entität und implementieren sie in der Verhaltensimplementierungsklasse.
Eingabeprüfungen in der App
Neben der Prüfung des semantischen Schlüssels gibt es weitere Prüfungen, die Sie durchführen müssen. Obwohl die generierte App es Ihnen ermöglicht, Daten anzulegen, zu lesen, zu aktualisieren und zu löschen, enthält sie noch keine Konsistenzprüfungen. Folglich können Sie Flugverbindungen für Fluggesellschaften anlegen, die nicht vorhanden sind oder bei denen Abflug- und Zielflughafen identisch sind.

Um dies zu verhindern, definieren Sie weitere Validierungen in der Verhaltensdefinition und implementieren sie in der Verhaltensimplementierungsklasse.
Nachrichtentexte anlegen
Bevor Sie die Validierung anlegen, müssen Sie die Texte anlegen, die Sie anzeigen möchten. Dies geschieht über eine Nachrichtenklasse. Eine Nachrichtenklasse ist eine Sammlung von bis zu 1000 Nachrichten, die zu einem bestimmten Anwendungsbereich gehören. Wie in der Abbildung dargestellt, hat jeder Text eine Nummer, die die Nachricht innerhalb der Nachrichtenklasse eindeutig identifiziert.

Um eine neue Nachrichtenklasse anzulegen, gehen Sie wie folgt vor:
Wählen Sie File→New→Other…, und geben Sie message in das Filterfeld ein.
Doppelklicken Sie auf den Eintrag Nachrichtenklasse in der Trefferliste, und geben Sie dann ein Paket, einen Namen und eine Beschreibung für die neue Nachrichtenklasse ein. Wählen Sie Next.
Ordnen Sie die Nachrichtenklasse einem Transportauftrag zu, und wählen Sie Fertigstellen.
Nachrichten können auch Platzhalter enthalten, die bei der Anzeige der Nachricht durch konkrete Werte ersetzt werden. Platzhalter werden durch das Et-Zeichen gefolgt von einer Zahl gekennzeichnet. Sie können in jeder Nachricht bis zu vier Platzhalter verwenden.
Validierung definieren
Um eine Validierung zu definieren, fügen Sie der Verhaltensdefinition Ihres Business-Objekts eine Validierungsdeklaration hinzu. In diesem Beispiel sollte die Validierung immer dann durchgeführt werden, wenn der Benutzer einen Datensatz sichert. Dies kann entweder beim Anlegen des Datensatzes oder bei einer nachträglichen Änderung des Datensatzes der Fall sein.

Wenn Sie die Validierung in der Verhaltensdefinition definieren, erhalten Sie eine Warnung, dass die entsprechende Methode nicht vorhanden ist. Verwenden Sie einen Quickfix (Tastenkombination STRG + 1), um die Methode zur Verhaltensimplementierung hinzuzufügen. Die Verhaltensimplementierung ist eine lokale Klasse innerhalb Ihres Behavior-Pools. Die Methodendefinition enthält den Zusatz FOR VALIDATE ON SAVE, der ihn als Implementierung der Validierung kennzeichnet. Sie hat den Importing-Parameter KEYS. Hierbei handelt es sich um eine interne Tabelle, die die Schlüssel der angelegten oder geänderten Objekte enthält. Sie verwenden diese, um die tatsächlichen Daten zu lesen, die der Benutzer eingegeben hat.
Der Zusatz FOR Connection~CheckSemanticKey verknüpft die Methode mit der Validierung CheckSemanticKey aus der Verhaltensdefinition. Verbindung ist hier der Aliasname der View-Entität Z_R_CONNECTION.

Wenn Sie eine Validierung definieren, müssen Sie auch deren Implementierung anlegen. Dies ist eine Methode im Behavior-Pool. Der einfachste Weg, dies zu tun, ist die Verwendung einer Schnellkorrektur. Positionieren Sie den Cursor auf den Namen der Validierung, und drücken Sie STRG + 1. ADT schlägt vor, die Methode anzulegen. Doppelklicken Sie auf den Vorschlag, um die Methode anzulegen.
Der Validierungsprozess
Notiz

Wenn das System eine Validierung auslöst, ruft es die entsprechende Implementierung auf. Der Importing-Parameter KEYS enthält die Schlüssel der geänderten Datensätze. Sie verwenden die Schlüssel, um die Felder der Datensätze zu lesen, die Sie mit Entity Manipulation Language (EML) benötigen. EML ist ein spezieller Satz von Anweisungen in ABAP, mit dem Sie Business-Objekte adressieren können.
Nachdem Sie die Daten gelesen haben, können Sie die von Ihnen benötigten Prüfungen durchführen. Wenn die Prüfung fehlschlägt, müssen Sie eine entsprechende Fehlermeldung ausgeben und vor allem dem Framework mitteilen, die Änderungen nicht in die Datenbank zu schreiben.

Die erste Aufgabe in einer Validierung besteht darin, die Benutzereingaben zu lesen. Dazu verwenden Sie die EML-Anweisung (Entity Manipulation Language) READ ENTITIES. Die Schlüssel der entsprechenden Datensätze werden mit den Importparameterschlüsseln an die Validierung übergeben.
Die Felder, die Sie zur Validierung des semantischen Schlüssels benötigen, sind Spediteur-ID für die Fluggesellschaft und ConnectionID für die Flugnummer.
Der Quelltextausschnitt verwendet das Schlüsselwort CORRESPONDING und eine Inline-Deklaration für die Ergebnismenge. Nachfolgend sehen Sie den äquivalenten Code, der explizit definierte Variablen verwendet, was das Verständnis der verwendeten Typen erleichtert.
12345678910111213
DATA read_keys TYPE TABLE FOR READ IMPORT zs4d400_r_connection.
DATA connections TYPE TABLE FOR READ RESULT zs4d400_r_connection.
read_keys = CORRESPONDING #( keys ).
READ ENTITIES OF zs4d400_r_connection IN LOCAL MODE
ENTITY Connection
FIELDS ( CarrierID ConnectionID )
WITH read_keys
RESULT connections.
Nachdem Sie die Benutzereingaben gelesen haben, können Sie die Werte von CarrierID und ConnectionID verwenden, um zu sehen, ob dieser semantische Schlüssel bereits in einem anderen Datensatz verwendet wurde als dem, den Sie gerade bearbeiten. Da sich die Schlüsselkombination entweder in der aktiven Tabelle oder in der Entwurfstabelle befinden kann, müssen Sie beides durchsuchen. Am effizientesten ist dies mit einer Union.

Die Ergebnismenge dieser Abfrage sollte immer leer sein. Ist dies nicht der Fall, gibt es mehr Datensätze mit derselben Kombination aus Spediteur-ID und Verbindungs-ID. Das bedeutet, dass der Datensatz, den der Benutzer gerade anlegen möchte, eine Dublette ist und abgelehnt werden muss.

Wenn die Kombination aus Spediteur-ID und Verbindungs-ID bereits vorhanden ist, gibt es einen Eintrag in der Tabelle check_result. In diesem Fall müssen Sie eine Meldung ausgeben.
Der erste Schritt besteht darin, ein Nachrichtenobjekt anzulegen. Dazu verwenden Sie die Selbstreferenz me und rufen die Methode new_message( ) auf. Die Parameter ID, Nummer und Schweregrad sind obligatorisch. ID ist der Name der Nachrichtenklasse, die die Nachricht enthält; Nummer ist die Nachrichtennummer. Der Schweregrad klassifiziert die Meldung als Erfolgs-, Informations-, Warn- oder Fehlermeldung. Die Verhaltensimplementierungsklasse enthält eine strukturierte Konstante ms, deren Komponenten die verschiedenen Schweregrade darstellen. In diesem Fall benötigen Sie den Schweregrad ms-error.
Die Methode hat auch die optionalen Importparameter v1, v2, v3 und v4. Sie verwenden diese, um Platzhalter durch konkrete Werte zu ersetzen. In diesem Beispiel wird der Platzhalter &1 durch den Fluggesellschaftscode und der Platzhalter &2 durch die Flugnummer ersetzt.
Das Ergebnis des Methodenaufrufs ist eine Objektreferenz. Im nächsten Schritt übergeben Sie das Objekt an die Laufzeit, sodass die Fehlermeldung an den OData-Service zurückgegeben und in der App-Vorschau angezeigt wird.

Damit die Laufzeit eine Meldung anzeigt, müssen Sie sie mit der Struktur reported melden. Dies ist ein impliziter Changing-Parameter aller Validierungsmethoden und eine tiefe Struktur. Sie enthält eine Komponente mit dem Aliasnamen der Entität. Diese Komponente ist eine interne Tabelle.
Um die Meldung zu melden, müssen Sie drei Schritte ausführen:
- Ergänzen Sie die interne Tabelle um den Schlüssel des betroffenen Satzes. Dies ist über die Feldgruppe %tky möglich. Wenn Sie solche Felder gruppieren, können Sie den Namen der Gruppe adressieren, anstatt jedes Feld einzeln ansprechen zu müssen.
- Hängen Sie das Nachrichtenobjekt an die Tabelle an. Dazu ordnen Sie die Objektreferenz des Nachrichtenobjekts der Komponente %msg der internen Tabelle zu.
- Binden Sie die Nachricht an das betroffene Feld. Dadurch wird sichergestellt, dass das Feld in der App hervorgehoben wird. Dies wiederum hilft dem Benutzer, besser in der App zu navigieren. Dazu verwenden Sie die Komponente %element der internen Tabelle.

In diesem Beispiel ist reported_record eine Struktur mit dem Zeilentyp der internen Tabelle reported-connection. Sie füllen die Komponente %tky mit dem Inhalt der Feldgruppe %tky in der Struktur connection. Diese Verbindungsstruktur dient als Arbeitsbereich für die interne Tabelle, die die vom Benutzer eingegebenen Daten enthält. Anschließend ordnen Sie das Nachrichtenobjekt, das Sie mit der Methode new_message( ) angelegt haben, der Komponente %msg zu. Zum Schluss verwenden Sie die Struktur %element, um die Nachricht an die Felder CarrierID und ConnectionID zu binden. %element enthält eine Komponente für jedes Feld in der Entität. Wenn Sie eine Komponente auf wahr setzen, wird das entsprechende Eingabefeld in der App hervorgehoben. Dazu verwenden Sie die strukturierte Konstante if_abap_behv=>mk. Dies hat die Komponente an für markiert/wahr und aus für nicht markiert/falsch.
Die globalen Konstanten abap_true und abap_false können an dieser Stelle nicht verwendet werden, da deren Datentypen nicht kompatibel sind.

Zusätzlich zur Ausgabe der Meldung müssen Sie der Laufzeit mitteilen, dass die fehlerhaften Daten nicht gesichert werden sollen. Dazu verwenden Sie die fehlgeschlagene Struktur der Validierungsmethode. Fehlgeschlagen ist ein impliziter Änderungsparameter, der in allen Validierungsmethoden vorhanden ist.
Um einen Datensatz als fehlgeschlagen zu melden, fügen Sie seine Feldgruppe %tky der Feldgruppe %tky der internen Tabelle failed-Connection hinzu.

Die nächste Validierung prüft, ob die Fluggesellschaft, die der Benutzer eingegeben hat, tatsächlich vorhanden ist. Der erste Schritt besteht darin, die Benutzereingaben mit der EML-Anweisung READ ENTITIES zu lesen. Dieses Mal müssen Sie nur das Feld Spediteur-ID lesen.

Die SELECT SINGLE -Anweisung liest Daten über die CDS-View-Entität /dmo/i_carrier und prüft, ob die angegebene Fluggesellschaft vorhanden ist. Ist dies der Fall, wird der Wert der globalen Konstante abap_true ('X') in das Feld exists gestellt. Wenn nach der SELECT-Anweisung initial ist, müssen Sie eine Meldung ausgeben, melden und den Datensatz wie im vorherigen Beispiel zur fehlgeschlagenen Struktur hinzufügen.
Die abschließende Validierung prüft, ob sich Herkunfts- und Zielflughafen unterscheiden. Der erste Schritt besteht darin, die Benutzereingaben mit einer READ ENTITIES -Anweisung zu lesen. Dieses Mal sind die Felder AirportFromID und AirportToID relevant.


Wenn Abflug- und Ankunftsflughafen identisch sind, müssen Sie die entsprechende Meldung ausgeben und die gemeldeten und fehlgeschlagenen Strukturen füllen. Der Quelltextauszug zeigt den relevanten Quelltext zum Anlegen der Nachricht an. Der Quelltext zum Füllen der gemeldeten und fehlgeschlagenen Strukturen ist derselbe wie in den vorherigen Beispielen.






