Remote Function Call (RFC) ermöglicht die synchrone Kommunikation zwischen SAP-Systemen. In ABAP Cloud werden RFC-Verbindungen über Communication Arrangements und den Destination Service konfiguriert, um eine sichere und wartbare Integration zu gewährleisten.
RFC in ABAP Cloud vs. Klassisches ABAP
Die RFC-Kommunikation in ABAP Cloud unterscheidet sich grundlegend vom klassischen Ansatz:
| Aspekt | Klassisches ABAP | ABAP Cloud |
|---|---|---|
| Konfiguration | SM59 RFC-Destination | Communication Arrangement |
| Aufruf | CALL FUNCTION … DESTINATION | Proxy-Klassen über IF_PROXY_CLIENT |
| Authentifizierung | In SM59 hinterlegt | OAuth2, Zertifikate, Principal Propagation |
| Monitoring | SMGW, ST22 | SAP Cloud ALM, BTP Cockpit |
| Fehlerbehandlung | COMMUNICATION_FAILURE | Exception-Klassen |
| Verfügbarkeit | Alle FuBas | Nur freigegebene Remote-enabled FuBas |
Kommunikationsszenarien
Szenarien-Übersicht
Es gibt drei Hauptszenarien für RFC in ABAP Cloud:
┌─────────────────────────────────────────────────────────────────┐│ Szenario 1: Cloud-to-Cloud ││ ┌──────────────┐ ┌──────────────┐ ││ │ ABAP Cloud │─────>│ ABAP Cloud │ ││ │ (BTP) │ RFC │ (BTP) │ ││ └──────────────┘ └──────────────┘ │├─────────────────────────────────────────────────────────────────┤│ Szenario 2: Cloud-to-On-Premise (via Cloud Connector) ││ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ ││ │ ABAP Cloud │─────>│ SAP Cloud │─────>│ S/4HANA │ ││ │ (BTP) │ │ Connector │ │ On-Premise │ ││ └──────────────┘ └───────────────┘ └──────────────┘ │├─────────────────────────────────────────────────────────────────┤│ Szenario 3: On-Premise-to-Cloud ││ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ ││ │ S/4HANA │─────>│ SAP Cloud │─────>│ ABAP Cloud │ ││ │ On-Premise │ │ Connector │ │ (BTP) │ ││ └──────────────┘ └───────────────┘ └──────────────┘ │└─────────────────────────────────────────────────────────────────┘Cloud-to-Cloud RFC
Bei Cloud-to-Cloud-Kommunikation verbinden sich zwei ABAP-Environment-Instanzen direkt:
Vorteile:
- Keine zusätzliche Infrastruktur nötig
- Automatische OAuth2-Authentifizierung
- Hohe Verfügbarkeit durch BTP-Infrastruktur
Einschränkungen:
- Nur remote-enabled Function Modules
- Keine klassischen BAPIs (nur released APIs)
Cloud-to-On-Premise RFC
Für die Verbindung zu On-Premise-Systemen wird der SAP Cloud Connector benötigt:
Komponenten:
- SAP Cloud Connector installiert im lokalen Netzwerk
- Virtual Host Mapping für RFC-Gateway
- Principal Propagation für Benutzerweiterleitung
Communication Arrangement einrichten
1. Communication Scenario anlegen
Das Communication Scenario definiert die erlaubten Outbound-Services:
@EndUserText.label: 'RFC zu S/4HANA'@ObjectModel.usageType.serviceQuality: #Cdefine abstract entity ZA_RFC_S4_SCENARIO{ // Metadata für Communication Scenario}Im ADT-Editor für Communication Scenarios:
Communication Scenario: Z_RFC_S4HANADescription: RFC-Kommunikation zu S/4HANA
Outbound Services:├── RFC Service│ ├── Service ID: Z_RFC_S4_SERVICE│ ├── Service Type: RFC│ └── Allowed Destinations: Z_S4HANA_RFC_*2. Communication System anlegen
Das Communication System beschreibt das Zielsystem:
┌──────────────────────────────────────────────────────────────┐│ Communication System: Z_S4HANA_PROD │├──────────────────────────────────────────────────────────────┤│ General Data: ││ ├── System ID: S4H ││ ├── System Name: S/4HANA Produktiv ││ └── System Type: SAP System ││ ││ Technical Data (RFC): ││ ├── Host: s4hana.company.com ││ ├── Port: 443 (via Cloud Connector) ││ ├── Virtual Host: s4hana-virtual:3300 ││ └── Client: 100 ││ ││ User for Outbound Communication: ││ └── Authentication: OAuth 2.0 / Basic / Certificate │└──────────────────────────────────────────────────────────────┘3. Communication Arrangement aktivieren
Das Arrangement verbindet Scenario mit System:
┌──────────────────────────────────────────────────────────────┐│ Communication Arrangement: Z_RFC_S4HANA_PROD │├──────────────────────────────────────────────────────────────┤│ Communication Scenario: Z_RFC_S4HANA ││ Communication System: Z_S4HANA_PROD ││ ││ Outbound Services: ││ └── Z_RFC_S4_SERVICE: Active ✓ ││ ├── Path: /sap/bc/srt/rfc/sap/ ││ └── Authentication: OAuth2ClientCredentials │└──────────────────────────────────────────────────────────────┘RFC-Aufruf über Destination Service
Destination konfigurieren
Im BTP Cockpit wird die RFC-Destination erstellt:
Name: S4HANA_RFCType: RFCProxyType: OnPremise (für Cloud Connector)
RFC Properties:├── jco.client.ashost: s4hana-virtual├── jco.client.sysnr: 00├── jco.client.client: 100├── jco.client.lang: DE├── jco.destination.pool_capacity: 10└── jco.destination.peak_limit: 20
Authentication:├── Type: BasicAuthentication├── User: RFC_USER└── Password: ********
Location ID: <Cloud Connector Location>RFC-Proxy generieren
Für den typsicheren RFC-Aufruf wird ein Proxy generiert:
CLASS zcl_s4_material_proxy DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. TYPES: BEGIN OF ty_material, matnr TYPE c LENGTH 18, maktx TYPE c LENGTH 40, meins TYPE c LENGTH 3, mtart TYPE c LENGTH 4, END OF ty_material, tt_materials TYPE STANDARD TABLE OF ty_material WITH EMPTY KEY.
METHODS constructor RAISING cx_http_dest_provider_error.
METHODS get_material_details IMPORTING iv_matnr TYPE matnr RETURNING VALUE(rs_result) TYPE ty_material RAISING cx_rfc_dest_provider_error cx_communication_failure.
METHODS search_materials IMPORTING iv_search_term TYPE string RETURNING VALUE(rt_result) TYPE tt_materials RAISING cx_rfc_dest_provider_error cx_communication_failure.
PRIVATE SECTION. DATA mo_destination TYPE REF TO if_rfc_destination.ENDCLASS.
CLASS zcl_s4_material_proxy IMPLEMENTATION. METHOD constructor. " RFC-Destination vom Destination Service abrufen mo_destination = cl_rfc_destination_provider=>create_by_cloud_destination( i_name = 'S4HANA_RFC' ). ENDMETHOD.
METHOD get_material_details. DATA: lv_matnr TYPE matnr, ls_material TYPE ty_material.
lv_matnr = iv_matnr.
" RFC-Aufruf über Proxy CALL FUNCTION 'BAPI_MATERIAL_GET_DETAIL' DESTINATION mo_destination->get_destination_name( ) EXPORTING material = lv_matnr IMPORTING material_general_data = ls_material EXCEPTIONS communication_failure = 1 system_failure = 2 OTHERS = 3.
IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_communication_failure EXPORTING textid = cx_communication_failure=>communication_failure. ENDIF.
rs_result = ls_material. ENDMETHOD.
METHOD search_materials. DATA: lt_matnr_range TYPE RANGE OF matnr, lt_materials TYPE tt_materials.
" Suchbereich aufbauen APPEND VALUE #( sign = 'I' option = 'CP' low = |*{ iv_search_term }*| ) TO lt_matnr_range.
" RFC-Aufruf CALL FUNCTION 'BAPI_MATERIAL_GETLIST' DESTINATION mo_destination->get_destination_name( ) TABLES matnrselection = lt_matnr_range matnrlist = lt_materials EXCEPTIONS communication_failure = 1 system_failure = 2 OTHERS = 3.
IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_communication_failure. ENDIF.
rt_result = lt_materials. ENDMETHOD.ENDCLASS.Verwendung in RAP
Integration des RFC-Proxys in einen RAP-Business-Object:
CLASS lhc_material DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS get_external_data FOR READ IMPORTING keys FOR FUNCTION Material~getExternalData RESULT result.ENDCLASS.
CLASS lhc_material IMPLEMENTATION. METHOD get_external_data. TRY. DATA(lo_proxy) = NEW zcl_s4_material_proxy( ).
LOOP AT keys INTO DATA(ls_key). DATA(ls_material) = lo_proxy->get_material_details( iv_matnr = ls_key-MaterialNumber ).
APPEND VALUE #( %tky = ls_key-%tky %param-Description = ls_material-maktx %param-BaseUnit = ls_material-meins %param-MaterialType = ls_material-mtart ) TO result. ENDLOOP.
CATCH cx_http_dest_provider_error cx_communication_failure INTO DATA(lx_error). " Fehlerbehandlung LOOP AT keys INTO ls_key. APPEND VALUE #( %tky = ls_key-%tky %fail = VALUE #( cause = if_abap_behv=>cause-unspecific ) ) TO failed-material. ENDLOOP. ENDTRY. ENDMETHOD.ENDCLASS.On-Premise vs. Cloud-to-Cloud
Cloud-to-Cloud RFC
Bei reiner Cloud-Kommunikation ist die Konfiguration einfacher:
CLASS zcl_cloud_rfc_client DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. METHODS call_remote_function IMPORTING iv_param TYPE string RETURNING VALUE(rv_result) TYPE string RAISING cx_rfc_dest_provider_error.ENDCLASS.
CLASS zcl_cloud_rfc_client IMPLEMENTATION. METHOD call_remote_function. " Direkte Cloud-Destination (ohne Cloud Connector) DATA(lo_destination) = cl_rfc_destination_provider=>create_by_cloud_destination( i_name = 'ABAP_CLOUD_SYSTEM_2' ).
" RFC-Aufruf zu anderem ABAP Cloud System CALL FUNCTION 'Z_REMOTE_FUNCTION' DESTINATION lo_destination->get_destination_name( ) EXPORTING iv_input = iv_param IMPORTING ev_output = rv_result EXCEPTIONS communication_failure = 1 system_failure = 2 OTHERS = 3.
IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_rfc_dest_provider_error. ENDIF. ENDMETHOD.ENDCLASS.BTP Destination für Cloud-to-Cloud:
Name: ABAP_CLOUD_SYSTEM_2Type: RFCProxyType: Internet
Authentication: OAuth2SAMLBearerAssertionToken Service URL: https://other-abap-system.authentication.eu10.hana.ondemand.com/oauth/token
Additional Properties:├── jco.client.ashost: other-abap-system-api.cfapps.eu10.hana.ondemand.com├── jco.client.sysnr: 00└── jco.client.client: 100On-Premise RFC mit Cloud Connector
Für On-Premise-Systeme ist zusätzliche Konfiguration im Cloud Connector erforderlich:
┌──────────────────────────────────────────────────────────────┐│ Cloud Connector Mapping │├──────────────────────────────────────────────────────────────┤│ Backend Type: ABAP System ││ ││ Virtual Host: s4hana-virtual ││ Virtual Port: 3300 ││ Internal Host: s4hana.internal.company.com ││ Internal Port: 3300 ││ ││ Protocol: RFC ││ Principal Type: X.509 Certificate (Recommended) ││ ││ Resources: ││ └── All (oder spezifische Function Modules) │└──────────────────────────────────────────────────────────────┘Fehlerbehandlung und Timeout
Exception-Klassen
CLASS zcl_rfc_handler DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. METHODS execute_rfc RETURNING VALUE(rv_result) TYPE string RAISING zcx_rfc_error.ENDCLASS.
CLASS zcl_rfc_handler IMPLEMENTATION. METHOD execute_rfc. TRY. DATA(lo_destination) = cl_rfc_destination_provider=>create_by_cloud_destination( i_name = 'S4HANA_RFC' ).
CATCH cx_rfc_dest_provider_error INTO DATA(lx_dest). " Destination nicht gefunden oder falsch konfiguriert RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING previous = lx_dest textid = zcx_rfc_error=>destination_not_found. ENDTRY.
" RFC-Aufruf mit detaillierter Fehlerbehandlung DATA lv_message TYPE c LENGTH 200.
CALL FUNCTION 'Z_REMOTE_FUNCTION' DESTINATION lo_destination->get_destination_name( ) IMPORTING ev_result = rv_result EXCEPTIONS communication_failure = 1 MESSAGE lv_message system_failure = 2 MESSAGE lv_message OTHERS = 3.
CASE sy-subrc. WHEN 0. " Erfolg RETURN.
WHEN 1. " Netzwerkfehler, Timeout, System nicht erreichbar RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>communication_failure message = CONV #( lv_message ).
WHEN 2. " ABAP-Fehler im Zielsystem (Dump, Exception) RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>system_failure message = CONV #( lv_message ).
WHEN OTHERS. " Unbekannter Fehler RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>unknown_error. ENDCASE. ENDMETHOD.ENDCLASS.Timeout-Konfiguration
Timeouts werden in der Destination konfiguriert:
Name: S4HANA_RFC
Additional Properties:├── jco.destination.expiration_time: 60000 " ms bis Connection-Cleanup├── jco.destination.expiration_period: 60000 " Prüfintervall├── jco.destination.max_get_time: 30000 " Max Wartezeit auf Connection├── jco.client.cpic_timeout: 120 " Sekunden für RFC-Call└── jco.destination.peak_limit: 10 " Max parallele ConnectionsRetry-Logik implementieren
CLASS zcl_rfc_retry_handler DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. CONSTANTS: c_max_retries TYPE i VALUE 3, c_retry_delay TYPE i VALUE 2000. " ms
METHODS call_with_retry IMPORTING iv_function TYPE rs38l_fnam RETURNING VALUE(rv_result) TYPE string RAISING zcx_rfc_error.ENDCLASS.
CLASS zcl_rfc_retry_handler IMPLEMENTATION. METHOD call_with_retry. DATA: lv_retries TYPE i, lv_message TYPE c LENGTH 200.
DATA(lo_destination) = cl_rfc_destination_provider=>create_by_cloud_destination( i_name = 'S4HANA_RFC' ).
WHILE lv_retries < c_max_retries. CALL FUNCTION iv_function DESTINATION lo_destination->get_destination_name( ) IMPORTING ev_result = rv_result EXCEPTIONS communication_failure = 1 MESSAGE lv_message system_failure = 2 MESSAGE lv_message OTHERS = 3.
CASE sy-subrc. WHEN 0. " Erfolg - sofort zurück RETURN.
WHEN 1. " Kommunikationsfehler - Retry sinnvoll lv_retries = lv_retries + 1.
IF lv_retries < c_max_retries. " Exponentielles Backoff DATA(lv_wait) = c_retry_delay * lv_retries. cl_abap_session_context=>sleep( lv_wait ). ENDIF.
WHEN 2. " Systemfehler - kein Retry, da Logikfehler RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>system_failure message = CONV #( lv_message ).
WHEN OTHERS. RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>unknown_error. ENDCASE. ENDWHILE.
" Max Retries erreicht RAISE EXCEPTION TYPE zcx_rfc_error EXPORTING textid = zcx_rfc_error=>max_retries_exceeded message = |Max. { c_max_retries } Versuche erreicht: { lv_message }|. ENDMETHOD.ENDCLASS.Monitoring und Troubleshooting
Logging implementieren
METHOD call_with_logging. DATA lo_log TYPE REF TO if_bali_log.
TRY. " Log erstellen lo_log = cl_bali_log=>create_with_header( header = cl_bali_header_setter=>create( object = 'Z_RFC_LOG' subobject = 'RFC_CALLS' external_id = |RFC_{ sy-datum }_{ sy-uzeit }| ) ).
" Start-Eintrag lo_log->add_item( item = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_information text = |RFC-Aufruf gestartet: { iv_function }| ) ).
DATA(lv_start) = utclong_current( ).
" RFC ausführen DATA(lv_result) = execute_rfc( iv_function ).
DATA(lv_end) = utclong_current( ). DATA(lv_duration) = cl_abap_utclong=>diff( high = lv_end low = lv_start ).
" Erfolg loggen lo_log->add_item( item = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_status text = |RFC erfolgreich, Dauer: { lv_duration-second } Sekunden| ) ).
rv_result = lv_result.
CATCH zcx_rfc_error INTO DATA(lx_error). " Fehler loggen lo_log->add_item( item = cl_bali_free_text_setter=>create( severity = if_bali_constants=>c_severity_error text = |RFC-Fehler: { lx_error->get_text( ) }| ) ).
RAISE EXCEPTION lx_error.
CLEANUP. " Log speichern IF lo_log IS BOUND. cl_bali_log_db=>get_instance( )->save_log( log = lo_log ). ENDIF. ENDTRY.ENDMETHOD.Häufige Fehler und Lösungen
| Fehler | Ursache | Lösung |
|---|---|---|
| COMMUNICATION_FAILURE | Netzwerk, Timeout | Cloud Connector prüfen, Timeout erhöhen |
| SYSTEM_FAILURE | Dump im Zielsystem | ST22 im Zielsystem prüfen |
| RFC_ERROR_LOGON_FAILURE | Authentifizierung | Credentials in Destination prüfen |
| RFC_ERROR_SYSTEM_BUSY | Überlastung | peak_limit erhöhen, Retry |
| RFC_ERROR_COMMUNICATION | Gateway-Problem | Cloud Connector neu starten |
Best Practices
| Thema | Empfehlung |
|---|---|
| Destination-Typ | RFC-Destination nur für echte RFC-Aufrufe, nicht für HTTP |
| Connection Pool | Angemessene pool_capacity und peak_limit setzen |
| Timeout | Realistische Timeouts basierend auf erwarteter Laufzeit |
| Fehlerbehandlung | Immer EXCEPTIONS auswerten, MESSAGE lv_message nutzen |
| Retry | Nur bei COMMUNICATION_FAILURE, nicht bei SYSTEM_FAILURE |
| Logging | Alle RFC-Aufrufe für Debugging loggen |
| Testing | Separate Destinations für DEV/QA/PROD |
| Security | Minimal notwendige RFC-Berechtigungen im Zielsystem |
Weiterführende Themen
- SAP Destination Service - Destinations konfigurieren
- HTTP Client - Alternative für REST-APIs
- RAP Custom Entities - Externe Daten in RAP einbinden