This is a test message to test the length of the message box.
Login
ABAP RAP Validierung
Erstellt von Software-Heroes

RAP - Validierung

250

Schauen wir uns einmal die Validierungen beim RAP Business Objekt an und wie sie im Framework umgesetzt werden.

Werbung


Validierungen sorgen im Business Objekt dafür, dass die Daten zu jeder Zeit konsistent sind und zwar zentral über alle Aktionen die auf dem Objekt abgesetzt werden. In diesem Artikel schauen wir uns an, wie man solche Validierungen anlegt und wie diese genau funktionieren.

 

Allgemein

Validierungen gehören zur Verhaltensdefinition eines Business Objekts und werden an der entsprechenden Entität definiert, wo sie auch gelten sollen. Sie werden beim Speichern der Daten ausgelöst und können für die einzelnen Events, wie Create, Update und Delete registriert werden. Weiterhin besteht auch die Möglichkeit das nur bei der Änderung eines einzelnen Feldes eine Validierung ausgelöst wird.

 

Allgemeine Validierung

Die allgemeine Validierung bezieht sich auf Validierungen die beim Speichern auf gewisse Events (Create, Update, Delete) immer ausgelöst werden, dazu das folgende Beispiel.

 

Anlegen

Definieren wir dazu die erste Validierung in einem Beispiel. Dazu beginnen wir mit der Erweiterung der Verhaltensdefinition:

validation validateKeyIsFilled on save { create; }

 

Eine Validierung wird mit dem Schlüsselwort "validation" angelegt, danach folgt der Name der Validierung und das Event bei dem es ausgelöst wird. In fast allen Fällen ist das "on save", also beim Speichern der Daten in der Speichersequenz. In der geschweiften Klammer geben wir nun mit, dass das Event nur beim Anlegen eines Datensatz auftritt. Nach der Aktivierung der Verhaltensdefinition bekommen wir die folgende Warnmeldung in Eclipse:

 

Es fehlt noch die Implementierung der Methode in der Verhaltensimplementierung (Klasse). Diese kannst du ganz leicht anlegen, indem du den Cursor auf den Namen der Validierung stellst und mit STRG + 1 im Quick Assist die Methode anlegst. Du landest zum Abschluss automatisch in der Klasse und der angelegten Methode.

CLASS lhc_Partner DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.
    METHODS validatekeyisfilled FOR VALIDATE ON SAVE
      IMPORTING keys FOR partner~validatekeyisfilled.
ENDCLASS.

CLASS lhc_Partner IMPLEMENTATION.
  METHOD validateKeyIsFilled.
  
  ENDMETHOD.
ENDCLASS.

 

Implementieren

Bevor wir mit der Implementierung der Methode beginnen, wollen wir uns zunächst einmal die Schnittstelle etwas genauer ansehen. Wie du oben in der Definition siehst, wurde ein Parameter in der Methodenschnittstelle definiert, prüfen wir dies nun in der Signatur:

 

Neben den Keys, stehen dir auch noch "failed" und "reported" zur Verfügung, die indirekt zur Methode dazu gehören.

  • KEYS - Übergabe der zu prüfenden Schlüssel an die Methode.
  • FAILED - Rückgabe der Schlüssel die fehlerhaft sind.
  • REPORTED - Rückgabe der fehlerhaften Schlüssel und Meldungen die den Fehler beschreiben.

 

Implementieren wir nun die Prüfung in der Methode. Da es sich hier um eine einfache Pflichtfeldprüfung handelt, ist die Logik entsprechend einfach und innerhalb des Loops erzeugen wir die Fehlermeldung:

LOOP AT keys INTO DATA(ls_key) WHERE PartnerNumber IS INITIAL.
  INSERT VALUE #( PartnerNumber = ls_key-PartnerNumber ) INTO TABLE failed-partner.

  INSERT VALUE #(
    PartnerNumber = ls_key-PartnerNumber
     %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'PartnerNumber is mandatory' )
  ) INTO TABLE reported-partner.
ENDLOOP.

 

Für die Befüllung der Meldung gibt es zwei Hilfsmethoden, die durch die Vererbung zur Verfügung stehen. Mit "new_message" können wir eine T100 Nachricht erzeugen und mit "new_message_with_text" reicht ein einfacher Text, um eine Meldung auszugeben:

 

Die Ausgabe der Meldung kann dann direkt im UI erfolgen in der unteren linken Ecke. Entsprechend der Klassifizierung über "severity", können wir die Farbe und das Icon beeinflussen (wie auch in der SAP GUI):

 

Validierung Feldebene

Die nächste Validierung wird nur ausgelöst, wenn sich das entsprechende Feld ändert. Dies ist vor allem dann sinnvoll, wenn wir gegen Schnittstellen oder Tabellen prüfen, ob dieser Wert existiert, um damit Performance einzusparen.

 

Anlegen

Die Anlage erfolgt wie im ersten Beispiel des Artikels über die Verhaltensdefinition und die anschließende Generierung in der Verhaltensimplementierung. Dieses Mal prüfen wir immer dann, wenn die beiden Stammdatenfelder sich ändern. Aus Sicht der Performance sollten wir dann eher zwei Validierungen daraus machen:

validation validateCoreData on save { field Country, PaymentCurrency; }

 

Implementieren

Wir hatten uns die Schnittstelle der Methode bereits beim ersten Beispiel angeschaut, daher wird dir auffallen sein, dass nur die Schlüssel an die Methode übergeben werden. Um nun an die fehlenden Informationen zu gelangen, müssen wir die Daten per EML lesen. Im Anschluss können wir über die Daten loopen und gegen die Stammdaten vergleichen.

READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
  ENTITY Partner
  FIELDS ( Country PaymentCurrency )
  WITH CORRESPONDING #( keys )
  RESULT DATA(lt_partner_data)
  FAILED DATA(ls_failed)
  REPORTED DATA(ls_reported).

LOOP AT lt_partner_data INTO DATA(ls_partner).
  SELECT SINGLE FROM I_Country
    FIELDS Country
    WHERE Country = @ls_partner-Country
    INTO @DATA(ld_found_country).
  IF sy-subrc <> 0.
    INSERT VALUE #( PartnerNumber = ls_partner-PartnerNumber ) INTO TABLE failed-partner.

    INSERT VALUE #(
      PartnerNumber = ls_partner-PartnerNumber
       %msg = new_message_with_text( text = 'Country not found in I_Country' )
       %element-country = if_abap_behv=>mk-on
    ) INTO TABLE reported-partner.
  ENDIF.

  SELECT SINGLE FROM I_Currency
    FIELDS Currency
    WHERE Currency = @ls_partner-PaymentCurrency
    INTO @DATA(ld_found_currency).
  IF sy-subrc <> 0.
    INSERT VALUE #( PartnerNumber = ls_partner-PartnerNumber ) INTO TABLE failed-partner.

    INSERT VALUE #(
      PartnerNumber = ls_partner-PartnerNumber
       %msg = new_message_with_text( text = 'Currency not found in I_Currency' )
       %element-paymentcurrency = if_abap_behv=>mk-on
    ) INTO TABLE reported-partner.
  ENDIF.
ENDLOOP.

 

Im Beispiel haben wir ein paar Dinge benutzt, die wir hier noch einmal erklären wollen:

  • READ - Beim Lesen haben wir den Schlüssel in der Feldauswahl nicht angegeben, dieser wird aber automatisch dazu gelesen, da er zur Identifizierung der Entität genutzt wird.
  • LOCAL MODE - Die Verifizierung des Users und des Status entfällt, das System geht davon aus das dies zuvor gemacht wurde. Mögliche Sperren durch den User werden vermeiden.
  • %ELEMENT - Beim Erzeugen der Fehlermeldungen haben wir zusätzlich das Element angegeben und aktiviert, dies sorgt dafür, dass das Feld noch zusätzlich markiert wird und die Fehlermeldung erscheint.

 

Vervollständigen

Wenn du die Validierung ausprobierst, wirst du feststellen, dass diese nicht beim Anlegen des Eintrags greift. Die eingestellte Validierung reagiert nur auf Änderung des Feldes, was bei der Anlage nicht der Fall ist, da es den Datensatz noch nicht gibt. Dazu müssen wir noch zusätzlich den Create mit aufnehmen, sodass zumindest auch bei der Anlage die Validierung durchlaufen wird.

validation validateCoreData on save { create; field Country, PaymentCurrency; }

 

Komplettes Beispiel

Das komplette Beispiel für die Verhaltensdefinition und die Implementierung findest du an dieser Stelle.

 

Verhaltensdefinition
managed implementation in class zbp_bs_demo_rappartner unique;
strict;

define behavior for ZBS_I_RAPPartner alias Partner
persistent table zbs_dmo_partner
lock master
authorization master ( instance )
{
  create;
  update;
  delete;

  validation validateKeyIsFilled on save { create; }
  validation validateCoreData on save { create; field Country, PaymentCurrency; }

  mapping for zbs_dmo_partner
  {
    PartnerNumber = partner;
    PartnerName = name;
    Street = street;
    City = city;
    Country = country;
    PaymentCurrency = payment_currency;
  }
}

 

Verhaltensimplementierung
CLASS lhc_Partner DEFINITION INHERITING FROM cl_abap_behavior_handler.
  PRIVATE SECTION.
    METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
      IMPORTING keys REQUEST requested_authorizations FOR Partner RESULT result.

    METHODS validatekeyisfilled FOR VALIDATE ON SAVE
      IMPORTING keys FOR partner~validatekeyisfilled.

    METHODS validatecoredata FOR VALIDATE ON SAVE
      IMPORTING keys FOR partner~validatecoredata.
ENDCLASS.

CLASS lhc_Partner IMPLEMENTATION.
  METHOD get_instance_authorizations.
  ENDMETHOD.


  METHOD validateKeyIsFilled.
    LOOP AT keys INTO DATA(ls_key) WHERE PartnerNumber IS INITIAL.
      INSERT VALUE #( PartnerNumber = ls_key-PartnerNumber ) INTO TABLE failed-partner.

      INSERT VALUE #(
        PartnerNumber = ls_key-PartnerNumber
         %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'PartnerNumber is mandatory' )
      ) INTO TABLE reported-partner.
    ENDLOOP.
  ENDMETHOD.


  METHOD validateCoreData.
    READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
      ENTITY Partner
      FIELDS ( Country PaymentCurrency )
      WITH CORRESPONDING #( keys )
      RESULT DATA(lt_partner_data)
      FAILED DATA(ls_failed)
      REPORTED DATA(ls_reported).

    LOOP AT lt_partner_data INTO DATA(ls_partner).
      SELECT SINGLE FROM I_Country
        FIELDS Country
        WHERE Country = @ls_partner-Country
        INTO @DATA(ld_found_country).
      IF sy-subrc <> 0.
        INSERT VALUE #( PartnerNumber = ls_partner-PartnerNumber ) INTO TABLE failed-partner.

        INSERT VALUE #(
          PartnerNumber = ls_partner-PartnerNumber
           %msg = new_message_with_text( text = 'Country not found in I_Country' )
           %element-country = if_abap_behv=>mk-on
        ) INTO TABLE reported-partner.
      ENDIF.

      SELECT SINGLE FROM I_Currency
        FIELDS Currency
        WHERE Currency = @ls_partner-PaymentCurrency
        INTO @DATA(ld_found_currency).
      IF sy-subrc <> 0.
        INSERT VALUE #( PartnerNumber = ls_partner-PartnerNumber ) INTO TABLE failed-partner.

        INSERT VALUE #(
          PartnerNumber = ls_partner-PartnerNumber
           %msg = new_message_with_text( text = 'Currency not found in I_Currency' )
           %element-paymentcurrency = if_abap_behv=>mk-on
        ) INTO TABLE reported-partner.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Die Validierungen sind ein mächtiges Instrument, um deine Daten innerhalb des Business Objekts sauber zu halten und dafür zu sorgen, dass nur valide Informationen gespeichert werden. Entsprechend solltest du dir bei der Anlage deines RAP BOs überlegen, welche Informationen, zu welchem Zeitpunkt, validiert werden sollen.


Enthaltene Themen:
RAPBTPValidierung
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


RAP - Semantischer Schlüssel

Kategorie - ABAP

Wofür benötigst du den semantischen Schlüssel und wie wird er im ABAP RESTful Programming Model dargestellt? Hier gibt es mehr dazu.

13.12.2024

RAP - Upload von Dateien (Stream)

Kategorie - ABAP

Wie kannst du einfach Dateien in deine RAP Entität laden und diese in ABAP zur Verfügung stellen? Hier schauen wir uns einmal die Details an.

10.12.2024

RAP - Report Pattern

Kategorie - ABAP

Wie ist das Report Pattern in RAP aufgebaut und was kannst du damit machen? Mehr dazu in diesem ABAP Artikel.

06.12.2024

RAP - Übersetzungs-App (Beispiel)

Kategorie - ABAP

Schauen wir uns einmal ein praktisches Beispiel für die Entwicklung einer RAP Anwendung im ABAP Environment an und wie du mit wenig Aufwand eine App erstellst.

02.08.2024

RAP - Custom Entity Wertehilfe (Deep Dive)

Kategorie - ABAP

Mit der Custom Entity hast du in RAP die meisten Freiheiten in der Entwicklung von ABAP Cloud Anwendungen, doch wie sieht es mit potentiellen Fehlern aus?

12.07.2024