Klassenbasierte Ausnahmen

Aus SAP-Wiki
Wechseln zu: Navigation, Suche

Mit dem Befehl "TRY - ENDTRY" lassen sich sehr komfortabel klassenbasierte Ausnahmen abfangen, die durch SAP während der Laufzeit im gleichen Programm oder aufgerufenen Programmen ausgelöst werden. Der Meldungstext wird durch die Ausnahmeklasse geliefert. Man muss nicht mehr wissen von welchem Programm in der Aufrufhierarchie die Ausnahme ausgelöst wurde.

Mit "txterror = oerror->get_text( )" wird der Fehler in die String-Variable TXTERROR geschrieben und kann dann z B in einer Meldung ausgegeben werden, in einem Write-Bildschirm oder ins Application Log.

TRY - ENDTRY

  • Mit "TRY. ... ENDTRY." wird der Codingbereich umschlossen, bei dem ein Fehler auftreten kann.
  • Der Catch-Bereich zur Behandlung des Fehlers wird ebenfalls durch den Try-Block eingeschlossen.
try.
 ...     "möglicher Fehlerauslöser
 catch.  "Fehlerbehandlung
endtry.

Catch

  • Mit "CATCH <ausnahmeklasse> wird eine bestimmte Ausnahme behandelt. Wenn in TRY-ENDTRY-Bereich eine Ausnahme ausgelöst wird, wird sofort der CATCH-Block angesprungen. Wenn eine andere Ausnahme ausgelöst wird, die nicht im CATCH-Block definiert ist, bricht das Programm mit einem Laufzeitfehler ab.

Ausnahmeklasse CX_ROOT

Alle Ausnahmeklassen leiten sich von der abstrakten Ausnahmeklasse CX_ROOT ab. Unter der Rootklasse CX_ROOT gibt es die abgeleiteten abstrakten Klassen

  • CX_DYNAMIC_CHECK
  • CX_NO_CHECK
  • CX_STATIC_CHECK.

Unter diesen Klassen gibt es weitere Klassen. In der Transaktion SE80 lässt sich diese Hierarchie anzeigen.

Ausnahmeklasse3.jpg


Bei der Ausnahmeklasse CX_DEMO_CONSTRUCTOR sieht man auch den Verberbungsbaum zur abstrakten Oberklasse CX_STATIC_CHECK und diese zur Klasse CX_ROOT.

KlassenbasAusnahme13.jpg

Identifikation Ausnahmeklasse

Es ist einfach die passende Ausnahmeklasse zu finden, wenn das Programm mit einem Shortdump abbricht.

Wenn z. B. eine Division durch Null gemacht wird, wird ein Laufzeitfehler ausgelöst

Data: lv_zahl type i.

lv_zahl = 4 / 0.

Im Text wird auf die Ausnahmeklasse CX_SY_ZERODIVIDE hingewiesen. Die kann nun verwendet werden.

Ausnahmeklasse1.jpg


Die Hierarchie zur obersten abstrakten Ausnahmeklasse CX_ROOT.

Ausnahmeklasse4.jpg


Eine Catch-Anweisung auf CX_SY_ZERODIVE behandelt nun die Ausnahme.

DATA: oerror           TYPE REF TO cx_root,
      lv_txterror      TYPE string,
      lv_txterror_long type string.

Data: lv_zahl type i.

TRY.
    lv_zahl = 4 / 0.

* Die Ausnahmeklasse CX_SY_ZERODIVIDE wird nun ausgelöst
* Das Objekt "oerror" beeinhaltet nun die Fehlerinformation
  CATCH CX_SY_ZERODIVIDE INTO oerror.
    lv_txterror      = oerror->get_text( ).      "Zuweisung Fehlertext der Ausnahmeklasse

*   Der Langtext wird in den String geschrieben (oft über 50 Zeichen)
    lv_txterror_long = oerror->get_longtext ( ). 
    MESSAGE i531(0u) WITH txterror.
ENDTRY.


Nun gibt es keinen Shortdump mehr, sondern eine aussagekräftige Meldung.

Ausnahmeklasse2.jpg

Ausnahmen in Aufrufhierarchie

Klassenbasierte Ausnahmen müssen nicht in dem Programm behandelt werden, in dem sie ausgelöst werden. Das hat den großen Vorteil, dass die klassenbasierten Ausnahmen durchgereicht werden können entlang der Aufrufhistorie und von einem übergeordneten Programm behandelt werden können.

HIer wird eine Ausnahme der Ausnahmeklasse CX_DEMO_CONSTRUCTOR ausgelöst mit dem Befehl

RAISE EXCEPTION TYPE <ausnahmeklasse>.

KlassenbasAusnahme2.jpg


Die klassenbasierte Ausnahme muss hier in in der Methode CX unter den Ausnahmen eingetragen sein.

KlassenbasAusnahme8.jpg


Wichtig ist die Checkbox KlassenbasAusnahme9.jpg, die der Methode sagt, dass hier eine klassenbasierte Ausnahme vorliegt. Man muss sich entscheiden innerhalb einer Methode zwischen klassenbasierten Ausnahmen und klassischen Ausnahmen.


Der aufrufende Report ZREBCX kann nun die klassenbasierte Ausnahme der Methode CX der Klasse ZREBERROR behandeln.

KlassenbasAusnahme6.jpg


Bei Funktionsbausteinen gibt es im Reiter "Ausnahmen" die gleiche Checkbox "Ausnameklassen", die für die Erzeugung einer klassenbasierten Ausnahme benötigt wird. Hier beim Funktionsbausetin FP_JOB_OPEN gibt es. nur klassischen Ausnahmen.

KlassenbasAusnahme10.jpg

Beispielcoding Dynamische Programmierung

Beim nachfolgenden Beispiel mit einer dynamischen Programmierung kann es passieren, dass Selektionsfelder übergeben oder Where-Felder abgefragt werden, die nicht existieren. Da diese Felder erst zur Laufzeit bekannt sind, kann die Syntaxprüfung diese Fehler nicht vorher abfangen.

Die Ausnahmeklasse CX_SY_DYNAMIC_OSQL_SEMANTICS löst im Fehlerfall eine Ausnahme aus, die dann behandelt werden kann.

DATA: oerror TYPE REF TO cx_root,
      txterror TYPE string.

 TRY.
     SELECT (gt_adressenfelder)
       INTO TABLE p_ct_itab
       FROM ztest
       WHERE (gt_where).

   CATCH cx_sy_dynamic_osql_semantics INTO oerror.
     txterror = oerror->get_text( ).
     MESSAGE i531(0u) WITH txterror.
 ENDTRY.

Constructor Ausnahmeklasse

Jede SAP-Ausnahmeklasse hat eine Constructor-Methode.

KlassenbasAusnahme11.jpg


KlassenbasAusnahme12.jpg


Hier wird der Constructor der Ausnahmeklasse CX_DEMO_CONSTRUCTOR mit einem Parameter MY_TEXT aufgerufen und SY-REPID übergeben.

KlassenbasAusnahme2.jpg


Das aktuelle Programm ist letztlich ein Bestandteil der Fehlerbeschreibung.

KlassenbasAusnahme7.jpg

Try- und Catch-Behandlung in einem Programm

  • Die Ausnahme wird in der Laufzeitumgebung von SAP ausgelöst oder über den Befehl "Raise Exception" im SAP-Programm.
REPORT demo_raise_exceptions.
DATA oref TYPE REF TO cx_root.
DATA text TYPE string.

TRY.
    RAISE EXCEPTION TYPE cx_demo_constructor
      EXPORTING
        my_text = sy-repid.
    CATCH cx_demo_constructor INTO oref.
      text = oref->get_text( ).
      WRITE / text.
ENDTRY.

Laufzeitfehler

  • Wirft ein Programm eine klassenbasierte Ausnahme mit "raise exception", dann muss dieses Programm oder ein anderes Programm in der Aufrufhierarchie diese Ausnahme behandeln. Erfolgt dies nicht, kommt es zu einem Laufzeitfehler
  • Hier ruft ein Report eine Methode CX der Klasse ZREBERROR auf, in der die klassenbasierte Ausnahme ausgelöst wird. Zur Provokation des Laufzeitfehlers wurde hier innerhalb des Try-Blocks der Catch auskommentiert.

KlassenbasAusnahme1.jpg


KlassenbasAusnahme2.jpg


KlassenbasAusnahme3.jpg


Mit dem Button KlassenbasAusnahme5.jpg kommt man zu einer ausführlicheren Beschreibung der Ausnahme.

KlassenbasAusnahme4.jpg


Sobald die Catch-Behandlung wieder aktiv ist, wird auch kein Laufzeitfehler mehr ausgelöst.

KlassenbasAusnahme6.jpg


KlassenbasAusnahme7.jpg

Web-Links

Literatur