
ABAP Quick - RFC Buffer
Here is a little tip from us about what can go wrong with the buffer when reading via RFC and what you should definitely pay attention to.
Table of contents
This is about a remote scenario that reads data from another system and makes it available. The call is made in a loop so that the RFC function module is called several times. This leads to an exciting result.
Structure
For the initial structure of the scenario, we provide a class in the first system that is to call the function module for us. For the sake of simplicity, we use a small loop and pass the index to the module, for which we expect the corresponding letter from the 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.
On the other side (system), the function module is implemented accordingly and marked as an RFC function module so that you can access it.
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.
Here we use a class based on a clean architecture, but not an object, but a static class that contains the data.
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.
Expectation
When the function module is called, the data is normally also kept in the global area as long as the user session is still running. After the session has ended, the data is deleted and the function group is set to zero. In the case of an RFC function module, we assume that the memory of the function module is deleted after each call, since the session in the target system is then completed.
As a result, a list of all letters should be output in the console one after the other, since a letter is called up with each call.
Result
The result of the loop now looks like this and therefore does not correspond to the expected result. The letters determined so far are also returned and the table is always only expanded to include the most recent letter.
Why does the result deviate from our expectation? After the function module is called, the session is not terminated on the target system and remains in existence as long as our session is running. If you would not expect between two systems at first, it is wanted if you want to collect large amounts of data and then work with database pointers.
As you can see, working with global variables and static attributes outside of buffer effects is very risky. We therefore advise you to always use objects and instances in order to be sure after a call that the instance is deleted and the memory has been completely cleaned up.
This little example is supposed to demonstrate what it can look like in complex classes if they are not used properly. We are not looking at the use of global variables for now, but there is the same risk here.
Conclusion
When designing RFC function modules, you should always pay attention to what happens to your data in the target system after a call and whether you really want to have this behavior. You shouldn't assume that the data will be cleaned up after the call and if you get too much, it could be due to the buffer on the other side.