
ABAP Tipp - Handling von Funktionsbausteinen
Wie gehst du eigentlich mit Funktionsbausteinen und der Fehlerbehandlung innerhalb von ABAP um? In diesem kleinen Tipp schauen wir uns die Behandlung auch im Rahmen von RFC an.
Inhaltsverzeichnis
In diesem Artikel gehen wir auf die Fehlerbehandlung von klassischen Funktionsbausteinen ein. Grundsätzlich brauchst du mit ABAP Cloud immer weniger Bausteine, da viele Funktionen in Klassen gewrappt wurden.
Einleitung
Das Handling von Funktionsbausteinen, vor allem als BAPIs, wird uns noch einige Jahre erhalten bleiben. Allerdings sollten wir als Entwickler auch mit den verschiedenen Zuständen der Verarbeitung umgehen können. Daher müssen wir wissen, wie Fehler in Funktionsbausteinen erzeugt werden, welche Informationen wir erhalten und wie wir sauber mit RFC-Funktionsbausteinen umgehen. Die verwendeten allgemeinen Dokumentationen findest du unten bei den Quellen.
Da es hier vor allem auch um die Fehlerbehandlung und Nachrichtenverarbeitung geht, verwenden wir den ABAP Message Logger, um die Meldungen und Fehler zu verarbeiten.
Fehlerbehandlung
Schauen wir uns dazu verschiedene Funktionsbausteine und Szenarien an. Der Funktionsbaustein ist erdacht und wir verwenden diesen nur zur Veranschaulichung.
Keine
In diesem sehr einfachen Szenario erhalten wir keine Ausnahme vom Funktionsbaustein. Wir geben Informationen hinein und erhalten eine Struktur mit Informationen. Hier arbeiten wir im Großteil mit der Rückgabe aus dem Funktionsbaustein. Grundsätzlich solltest du die Signatur des Funktionsbausteins prüfen, ob dieser nicht Ausnahmen enthält.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information.
Exceptions
Im nächsten Beispiel definieren wir EXCEPTIONS, dabei handelt es sich nicht um Ausnahmen aus der objektorientierten Entwicklung, sondern um klassische Ausnahmen. Nach dem Schlüsselwort findest du dann einige definierte Ausnahmen, wie zum Beispiel NOT_FOUND und die Zuweisung zu einem SUBRC. Grundsätzlich müssen nicht alle Ausnahmen abgefangen und zugeordnet werden, du kannst auch den Rest unter OTHERS zuweisen. Hierbei handelt es sich um eine generische Ausnahme, die alles übernimmt. Hilft vor allem, wenn die Ausnahmen des Funktionsbausteins später einmal erweitert werden.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
EXCEPTIONS
not_found = 1
OTHERS = 2.
Wird die Ausnahme ausgelöst, dann wird der SY-SUBRC auf den definierten Wert gesetzt. Im Nachgang zum Funktionsbaustein, solltest du dann darauf reagieren. Fehlermeldungen werden dann meist in die Systemfelder geschrieben. In diesem Fall können wir über das Log Objekt die Systemfelder nehmen und speichern.
IF sy-subrc <> 0.
log->add_message_system( ).
ENDIF.
Je nach Fehler solltest du auch die Weiterverarbeitung ändern, also entweder darauf reagieren, abbrechen oder den Datensatz invalidieren. Oft sieht man in Coding, dass nach einem fehlerhaften Aufruf weitergemacht wird und nicht einmal der Fehler protokolliert wird.
Return
Bei der Verwendung von BAPIs und anderen Funktionsbausteinen wird meist eine RETURN Parameter vom Typ BAPIRET2 verwendet. Hierbei handelt es sich um einen standardisierten Typen mit Informationen zu Meldungen und Nachrichten.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
return = return.
Oft ist das Handling der Meldungen etwas kompliziert, da entweder die ganze Tabelle geprüft wird und dann meist eine Fehlermeldung erzeugt wird. Über das Log können wir alle Meldungen direkt sichern. Über die Hilfsmethoden, wie zum Beispiel HAS_ERROR, können wir dann prüfen, ob es Fehler bei der Verarbeitung gab.
log->add_message_bapis( return ).
RFC Funktionsbaustein
Da du nun die Grundlagen für normale Funktionsbausteine kennst, schauen wir uns einmal die Verarbeitung mit RFC (Remote Function Call) Funktionsbausteinen an. Hierbei verwenden wir einen Funktionsbaustein und ergänzen dabei das Schlüsselwort DESTINATION, um über eine Verbindung den Funktionsbaustein auf einem anderen System aufzurufen.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS' DESTINATION destination
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information.
Allerdings fehlt hier nun die Fehlerbehandlung. Bei RFC Aufrufen kommen nun weitere Fehlerquellen hinzu, zum Beispiel kann das Zielsystem nicht erreichbar sein, der User ist gesperrt oder es fehlen Berechtigungen. Daher müssen nun Systemausnahmen definiert werden, die es am eigentlichen Funktionsbaustein nicht gibt. Die Meldungen schreiben wir dazu in eine eigene Variable.
DATA rfc_message TYPE c LENGTH 255.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS' DESTINATION destination
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
EXCEPTIONS
communication_failure = 1 MESSAGE rfc_message
system_failure = 2 MESSAGE rfc_message
OTHERS = 3.
Meist findest du auch wichtige Nachrichten zum Fehlergrund in der Nachricht. Daher solltest du eine Meldung zum Abbruch zu deinem Log hinzufügen und dann noch einmal die Meldung aus der Verarbeitung. In diesem Fall könnte die Verarbeitung der Meldungen so aussehen.
IF sy-subrc = 1.
log->add_message( class = 'Z_AML'
type = 'E'
number = '001' ).
log->add_message_text( rfc_message ).
ELSEIF sy-subrc = 2.
log->add_message( class = 'Z_AML'
type = 'E'
number = '002' ).
log->add_message_text( rfc_message ).
ELSE.
log->add_message( class = 'Z_AML'
type = 'E'
number = '003' ).
ENDIF.
Vollständiges Beispiel
Hier noch einmal das vollständige Beispiel aus dem Artikel. Da der Funktionsbaustein sehr wahrscheinlich nicht auf deinem System sein wird, kannst du die Aufrufe mit anderen Bausteinen nachstellen.
CLASS zcl_bs_demo_function_calls DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
DATA character TYPE c LENGTH 10.
DATA number TYPE i.
DATA returned_information TYPE string.
DATA log TYPE REF TO zif_aml_log.
METHODS handle_no_error.
METHODS handle_standard_error.
METHODS handle_bapi_return.
METHODS handle_rfc_call.
ENDCLASS.
CLASS zcl_bs_demo_function_calls IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
log = zcl_aml_log_factory=>create( ).
handle_no_error( ).
handle_standard_error( ).
handle_bapi_return( ).
handle_rfc_call( ).
ENDMETHOD.
METHOD handle_no_error.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information.
ENDMETHOD.
METHOD handle_standard_error.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
log->add_message_system( ).
ENDIF.
ENDMETHOD.
METHOD handle_bapi_return.
DATA return TYPE STANDARD TABLE OF bapiret2 WITH EMPTY KEY.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS'
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
return = return.
log->add_message_bapis( return ).
ENDMETHOD.
METHOD handle_rfc_call.
DATA destination TYPE string.
DATA rfc_message TYPE c LENGTH 255.
CALL FUNCTION 'Z_BS_DEMO_INFORMATIONS' DESTINATION destination
EXPORTING
id_char = character
id_number = number
IMPORTING
es_info = returned_information
EXCEPTIONS
communication_failure = 1 MESSAGE rfc_message
system_failure = 2 MESSAGE rfc_message
OTHERS = 3.
IF sy-subrc = 1.
log->add_message( class = 'Z_AML'
type = 'E'
number = '001' ).
log->add_message_text( rfc_message ).
ELSEIF sy-subrc = 2.
log->add_message( class = 'Z_AML'
type = 'E'
number = '002' ).
log->add_message_text( rfc_message ).
ELSE.
log->add_message( class = 'Z_AML'
type = 'E'
number = '003' ).
ENDIF.
ENDMETHOD.
ENDCLASS.
Fazit
Die Behandlung von Fehlermeldungen bei Funktionsbausteinen wird auch in der modernen Entwicklung noch eine Rolle spielen. Daher solltest du hier auch die Fehlerbehandlung vollständig durchführen und keine offenen Stellen im Quellcode und nach Aufrufen lassen. Bei RFC Funktionsbausteinen kommen noch einmal zusätzliche Aufgabe hinzu, die du auf keinen Fall vergessen solltest.
Quelle:
SAP Help - CALL FUNCTION (Parameter)
SAP Help - CALL FUNCTION (Exception Handling)