This is a test message to test the length of the message box.
Login
ABAP Tipp RFC Puffer
Erstellt von Software-Heroes

ABAP Tipp - RFC Puffer

158

Hier ein kleiner Tipp von uns, was beim Lesen über RFC mit dem Puffer so alles schief gehen kann und auf was du dabei unbedingt achten solltest.

Werbung


Hierbei geht es um ein Remoteszenario, das Daten aus einem anderen System liest und diese zur Verfügung stellt. Der Aufruf erfolgt in einer Schleife, sodass der RFC Funktionsbaustein mehrmals aufgerufen wird. Dadurch kommt es zu einem spannenden Ergebnis.

 

Aufbau

Für den initialen Aufbau des Szenarios stellen wir eine Klasse im ersten System zur Verfügung, die den Funktionsbaustein für uns aufrufen soll. Der Einfachheit verwenden wir eine kleine Schleife und übergeben den Index an den Baustein, dafür erwarten wir den entsprechenden Buchstaben aus dem Alphabet.

CLASS zcl_test_rfc_call DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_test_rfc_call IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    DATA:
      lt_letters TYPE string_table.

    DO 26 TIMES.
      DATA(ld_index) = sy-index - 1.

      CALL FUNCTION 'Z_RFC_BUFFER' DESTINATION 'DUMMY'
        EXPORTING
          id_index   = ld_index
        IMPORTING
          et_letters = lt_letters.

      out->write( concat_lines_of( lt_letters ) ).
    ENDDO.
  ENDMETHOD.
ENDCLASS.

 

Auf der anderen Seite (System) wird entsprechend der Funktionsbaustein implementiert und als RFC Funktionsbaustein gekennzeichnet, damit du darauf zugreifen kannst.

FUNCTION Z_RFC_BUFFER
  IMPORTING
    VALUE(ID_INDEX) TYPE SYINDEX
  EXPORTING
    VALUE(ET_LETTERS) TYPE STRING_TABLE.

  et_letters = lcl_function=>get_letter( id_index ).
ENDFUNCTION.

 

Hier verwenden wir nach einer sauberen Architektur eine Klasse, allerdings kein Objekt, sondern eine statische Klasse, die die Daten enthält.

CLASS lcl_function DEFINITION FINAL.
  PUBLIC SECTION.
    CLASS-DATA:
      gt_letters TYPE string_table.

    CLASS-METHODS:
      get_letter
        IMPORTING
                  id_index          TYPE syindex
        RETURNING VALUE(rt_letters) TYPE string_table.

  PRIVATE SECTION.
    CLASS-METHODS:
      find_letter
        IMPORTING
          id_index TYPE syindex.
ENDCLASS.

CLASS lcl_function IMPLEMENTATION.
  METHOD get_letter.
    find_letter( id_index ).

    rt_letters = gt_letters.
  ENDMETHOD.


  METHOD find_letter.
    INSERT CONV string( substring( val = sy-abcde off = id_index len = 1 ) ) INTO TABLE gt_letters.
  ENDMETHOD.
ENDCLASS.

 

Erwartung

Beim Aufruf des Funktionsbausteins werden im Normalfall auch die Daten im globalen Bereich gehalten, solange die  Anwendersession noch läuft. Nach dem Beenden der Session werden die Daten gelöscht und eine Funktionsgruppe auf Null gesetzt. Im Fall eines RFC Funktionsbausteins, gehen wir also davon aus, dass nach jedem Aufruf der Speicher des Funktionsbausteins gelöscht wird, da dann die Session im Zielsystem abgeschlossen ist.

Im Ergebnis sollte also in der Console eine Liste aller Buchstaben nacheinander ausgegeben werden, da mit jedem Aufruf ein Buchstabe abgerufen wird.

 

Ergebnis

Das Ergebnis der Schleife sieht nun also wie folgt aus und entspricht damit nicht dem erwarteten Ergebnis. Die bisherig ermittelten Buchstaben werden ebenfalls zurückgegeben und die Tabelle immer nur um den aktuellsten Buchstaben erweitert.

 

Wieso weicht das Ergebnis von unserer Erwartung ab? Nach dem Aufruf des Funktionsbausteins wird die Session auf dem Zielsystem nicht abgebaut und bleibt so lange existent, wie auch unsere Session läuft. Würde man zwischen zwei Systemen erst einmal nicht erwarten, ist aber so gewollt, wenn man einmal große Datenmengen abholen möchte und dann mit Datenbankzeigern arbeitet.

Wie du siehst ist die Arbeit mit globalen Variablen und statischen Attributen außerhalb von Puffereffekten sehr riskant. Wir raten dir daher immer auf Objekte und Instanzen zu setzen, um so nach einem Aufruf sicher zu sein, dass die Instanz gelöscht wird und der Speicher komplett bereinigt wurde.

Dieses kleine Beispiel soll demonstrieren wie es auch in komplexen Klassen aussehen kann, wenn diese nicht sauber verwendet werden. Wir betrachten dabei erst einmal nicht die Verwendung von globalen Variablen, hier besteht aber das gleiche Risiko.

 

Fazit

Beim Design von RFC Funktionsbausteinen solltest du immer darauf achten, was nach einem Aufruf mit deinen Daten im Zielsystem passiert und ob du dieses Verhalten wirklich haben möchtest. Du solltest nicht davon ausgehen das die Daten nach dem Aufruf aufgeräumt werden und wenn du zu viel erhältst, könnte es am Puffer auf der anderen Seite liegen.


Enthaltene Themen:
TippRFCPufferFehler
Kommentare (1)



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.


ABAP in der Praxis - Modern ABAP

Kategorie - ABAP

In dieser kleinen Aufgabe schauen wir uns bestehenden klassischen ABAP Quellcode an und versuchen diesen nach Modern ABAP zu optimieren.

27.08.2024

ABAP Tipp - Performance Datenfilterung

Kategorie - ABAP

Welche Anweisung verwendest du in ABAP zur Filterung von internen Tabellen und ist diese performant? In diesem Artikel mehr dazu.

13.08.2024

ABAP in der Praxis - Typkonvertierung

Kategorie - ABAP

Wie würdest du diese Typkonvertierung in ABAP durchführen? Ein Beispiel aus der Praxis und ein Lösungsvorschlag.

16.07.2024

ABAP Tipp - RFC Fehlerbehandlung

Kategorie - ABAP

Wie behandelt man eigentlich Fehler, wenn man über eine Destination im Funktionsbaustein kommuniziert? Mehr dazu in unserem Tipp.

05.03.2024

ABAP Tipp - CLEAR right

Kategorie - ABAP

Richtig löschen? In diesem Artikel wollen wir uns einmal anschauen, wann es Sinn macht zu löschen und wie du effektiv vorgehen kannst.

12.05.2023