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

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)
Werbung

ABAP Tipp - Aufbau von Testdaten

Kategorie - ABAP

Welche Herausforderungen hat man beim Aufbau von Testtabellen und Testdaten und wie kann dir die maschinelle Verarbeitung dabei helfen.

25.06.2021

ABAP Tipp - Wait for Task

Kategorie - ABAP

Heute einmal einen Tipp für die asynchrone Verarbeitung oder wenn ihr in speziellen Situationen die Verarbeitung in einen separaten Task geben wollt. Wie geht es im Anschluss weiter?

05.03.2021

ABAP Tipp - Performance INSERT vs VALUE

Kategorie - ABAP

In diesem Artikel schauen wir uns einmal die Performance der Einfüge-Operationen APPEND, INSERT und VALUE im Hinblick auf Tabellen an und bewerten die Performance und Stabilität bei der Entwicklung.

26.02.2021

ABAP Tipp - Suche im Quellcode

Kategorie - ABAP

Manchmal ist die Suche über verschiedene Quellcode in einem System nötig. Wir zeigen dir wie es in der SAP GUI und in Eclipse funktioniert.

24.04.2020

ABAP Tipp - Icons

Kategorie - ABAP

Icons oder auch Ikonen in SAP finden und richtig nutzen? Hier ein kleiner Guide zum Umgang mit den Bildern für unterschiedliche Zwecke.

06.03.2020