ABAP Function Modules & RFC: Synchronous, Asynchronous, tRFC, qRFC – Hands-On Integration Tutorial | Part 41 | FreeLearning365

 

ABAP Function Modules & RFC: Synchronous, Asynchronous, tRFC, qRFC – Hands-On Integration Tutorial | Part 41 | FreeLearning365

Function Modules, RFC & tRFC/qRFC – Connecting SAP to the World: A 25,000+ Word Hands-On Masterclass

Day 11 of the S/4HANA ABAP Development & Fiori Track

By @FreeLearning365 and Tech Partner @techbook24

Introduction: The Portal That Needed Real-Time SAP

TechBook24’s e‑commerce platform is a Node.js application running on Azure. It already creates purchase orders via the OData service Arjun built in Part 38. But the business now requires an additional check: before the portal even sends a PO, it must validate whether the total value exceeds the vendor’s negotiated limit — and it must do so in real time. Waiting for a batch job or a database poll is not acceptable. The portal needs to ask SAP directly: “Is this PO amount okay for this vendor?” and get an instant yes/no response.

This is where RFC (Remote Function Call) comes in. ABAP function modules can be marked as remote‑enabled, allowing external systems to invoke them via SAP’s proprietary RFC protocol or via standard Web Services. In this tutorial, Arjun will refactor the price‑check logic from the BAdI implementation (Part 35) into a clean, reusable function module, enable it for RFC, and then demonstrate it being called from within SAP and from an external Python client using the pyrfc library. He’ll also dive into asynchronous and transactional RFC to ensure guaranteed delivery even when the network is unreliable. By the end, you’ll have a complete integration scenario — from ABAP function module to external client — and a deep understanding of when to use each RFC flavor.

This is not just about writing code; it’s about building bridges between systems. Let’s start building.

1. Function Modules – The Building Blocks of Reusability

1.1 What Are Function Modules?

A function module is a named, reusable ABAP routine with a well‑defined interface. It belongs to a function group (also called a function pool), which is a container that can hold multiple function modules and manage a shared state via global data. Function modules are called with the CALL FUNCTION statement and can have importing, exporting, changing, and tables parameters, as well as raise exceptions.

Arjun decides to extract the vendor price limit validation into a function module so that it can be reused by:

  • The BAdI implementation (calling it instead of inline code)
  • The OData service (to validate before creating a PO)
  • The external e‑commerce portal via RFC

This is the principle of encapsulation — business logic in one place, no duplication.

1.2 Creating a Function Group and Module in SE37

Arjun opens transaction SE37 (Function Builder). He first creates a function group via Goto → Function Groups → Create Group. He enters ZFG_PURCH_VALID and short text “Purchase Order Validation Functions”. This generates a main program SAPLZFG_PURCH_VALID and an include LZFG_PURCH_VALIDTOP where global data can be declared.

Now he creates the function module: SE37 → enter Z_RFC_CHECK_PO_LIMIT → Create. He selects the function group ZFG_PURCH_VALID. The Function Builder opens.

Screenshot Description: SE37 initial screen with the new function module name and function group assigned.

1.3 Defining the Interface – Parameters and Exceptions

Arjun designs a clean interface:

  • Importing: IV_LIFNR (vendor), IV_EKORG (purch. org.), IV_NETWR (net value), IV_WAERS (currency), IV_DATE (date for validity).
  • Exporting: EV_VALID (abap_bool), EV_LIMIT (netwr value of the limit), EV_MESSAGE (string).
  • Tables: None for this simple check. But he adds a TABLES parameter ET_MESSAGES of type BAPIRET2 for future error details.
  • Exceptions: CX_NO_VENDOR_LIMIT (no limit data found), CX_LIMIT_EXCEEDED (value exceeds).

He enters these in the respective tabs. He makes sure to set the Processing Type to “Remote-Enabled Module” by checking the radio button in the “Attributes” tab. This flag is what enables RFC.

Screenshot Description: SE37 function module builder with the Import/Export tabs filled and the “Remote-Enabled” box checked.

1.4 Implementing the Logic

In the “Source Code” tab, Arjun writes:

FUNCTION Z_RFC_CHECK_PO_LIMIT.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_LIFNR) TYPE  LFA1-LIFNR
*"     VALUE(IV_EKORG) TYPE  EKKO-EKORG
*"     VALUE(IV_NETWR) TYPE  EKPO-NETWR
*"     VALUE(IV_WAERS) TYPE  EKKO-WAERS
*"     VALUE(IV_DATE)  TYPE  SY-DATUM DEFAULT SY-DATUM
*"  EXPORTING
*"     VALUE(EV_VALID) TYPE  ABAP_BOOL
*"     VALUE(EV_LIMIT) TYPE  EKPO-NETWR
*"     VALUE(EV_MESSAGE) TYPE  STRING
*"  TABLES
*"      ET_MESSAGES STRUCTURE  BAPIRET2 OPTIONAL
*"  EXCEPTIONS
*"      CX_NO_VENDOR_LIMIT
*"      CX_LIMIT_EXCEEDED
*"----------------------------------------------------------------------

  DATA: lv_limit TYPE zvenpr_limit-limit_netwr,
        lv_waers TYPE zvenpr_limit-waers.

  " 1. Read limit from custom table
  SELECT SINGLE limit_netwr waers
    FROM zvenpr_limit
    WHERE lifnr = @iv_lifnr
      AND ekorg = @iv_ekorg
      AND valid_from <= @iv_date
      AND valid_to >= @iv_date
    INTO ( @lv_limit, @lv_waers ).

  IF sy-subrc <> 0.
    RAISE cx_no_vendor_limit.
  ENDIF.

  ev_limit = lv_limit.

  " 2. Compare amounts (assuming same currency or use conversion, simplified here)
  IF iv_waers <> lv_waers.
    " In real life, call currency conversion; here we just fail for simplicity
    ev_valid = abap_false.
    ev_message = |Currency mismatch: PO currency { iv_waers } vs limit currency { lv_waers }|.
    RAISE cx_limit_exceeded.
  ENDIF.

  IF iv_netwr > lv_limit.
    ev_valid = abap_false.
    ev_message = |PO net value { iv_netwr } exceeds vendor limit { lv_limit }|.
    RAISE cx_limit_exceeded.
  ELSE.
    ev_valid = abap_true.
    ev_message = 'OK'.
  ENDIF.

ENDFUNCTION.

He uses the custom table ZVENPR_LIMIT created in Part 35. Note the use of inline declarations and the exception mechanism. When RAISE is used in an RFC function, the exception is transmitted back to the caller, where it can be caught with SY-SUBRC or exception handling in the calling system.

1.5 Testing in SE37 – The Function Module Test Screen

He saves and activates. Then he presses F8 (Test) in SE37. The test screen appears, showing the import parameters. He enters vendor 2000, net value 120,000, currency USD, and executes. The function returns EV_VALID = '' and EV_MESSAGE = 'PO net value 120,000 exceeds vendor limit 100,000', and raises the exception. He tests with value 50,000 — success. The function module works.

2. Function Groups and Global State – A Double-Edged Sword

2.1 The Purpose of Global Data in Function Groups

A function group can hold global data that persists across multiple function module calls within the same session. This is sometimes used to cache data. For example, Arjun could store the vendor limit table in a global internal table to avoid repeated DB reads. He modifies the function group’s TOP include:

DATA: gt_limit_cache TYPE SORTED TABLE OF zvenpr_limit WITH UNIQUE KEY lifnr ekorg.

Then in the function module, before the SELECT, he checks if the vendor is already cached. This is stateful programming. It can improve performance but can also cause subtle bugs if the cache becomes stale or if the function group is used in parallel with different session contexts. He decides to keep the function stateless for RFC (each RFC call is a new session by default) but use the cache in local ABAP calls where the function group is loaded once per session. He documents this clearly.

2.2 Locking and Unlocking – The ENQUEUE/DEQUEUE Pattern

Function modules for updating data often use ENQUEUE and DEQUEUE function modules to lock objects. Arjun mentions this is critical for RFC updates to avoid data inconsistency. He doesn’t need it for a read‑only validation, but he would for a PO creation API.

3. RFC – Remote Function Call in Depth

3.1 Synchronous RFC (sRFC)

The default RFC type is synchronous. The calling program waits until the function has finished executing in the remote system and receives the results. Arjun’s function module is synchronous. He configures an RFC destination in transaction SM59 to show how an ABAP program in TechBook24’s central system could call the same function in another SAP system (like a legacy ECC). But the primary use is external.

For external consumption, the same function is exposed as an RFC. An external client using SAP NCo (SAP .NET Connector) or pyrfc (Python) can call it. Arjun demonstrates with Python later. For now, let’s test RFC within ABAP.

3.2 Configuring an RFC Destination (SM59) for ABAP-to-ABAP

He creates a destination Z_RFC_VALID_DEST pointing to the same system (for testing) or to a remote system. SM59 → “ABAP Connections” → Create. He enters:

  • RFC Destination: Z_RFC_VALID_DEST
  • Connection Type: 3 (ABAP System)
  • Target Host: vhcalhci.dummy.nodomain (or actual IP)
  • System Number: 00
  • Client: 200
  • Language: EN
  • User: RFCUSER / password.

He tests the connection with the “Connection Test” button. Then “Remote Logon” to verify.

3.3 Calling the RFC from ABAP

A simple program:

DATA: lv_valid TYPE abap_bool,
      lv_limit TYPE ekpo-netwr,
      lv_msg   TYPE string.

CALL FUNCTION 'Z_RFC_CHECK_PO_LIMIT'
  DESTINATION 'Z_RFC_VALID_DEST'
  EXPORTING
    iv_lifnr = '0000002000'
    iv_ekorg = '1000'
    iv_netwr = 120000
    iv_waers = 'USD'
    iv_date  = sy-datum
  IMPORTING
    ev_valid = lv_valid
    ev_limit = lv_limit
    ev_message = lv_msg
  EXCEPTIONS
    cx_no_vendor_limit = 1
    cx_limit_exceeded  = 2
    OTHERS             = 3.
IF sy-subrc = 0.
  WRITE: / 'Valid:', lv_valid.
ELSE.
  WRITE: / 'Exception:', lv_msg.
ENDIF.

He runs the report; it connects, calls the RFC, and displays the result. Even within the same system, using DESTINATION forces the function to run in a separate RFC context, which is good for testing.

4. Asynchronous RFC (aRFC) – Fire and Forget

4.1 The Need for Asynchronous Calls

The e‑commerce portal needs to create a PO, but it doesn’t want to wait for the entire SAP processing (which might include workflow and email generation). Instead, it wants to send the PO data and continue immediately. Asynchronous RFC (aRFC) allows the caller to continue without waiting for the function to finish. The function must be defined as REMOTE-ENABLED and the call uses CALL FUNCTION ... STARTING NEW TASK. The result is not returned directly; instead, a callback or polling is needed.

Arjun creates another function module Z_RFC_CREATE_PO_ASYNC that creates a PO using BAPI_PO_CREATE1. He marks it as remote-enabled and sets the “Asynchronous” attribute? Actually, aRFC doesn’t require a special flag beyond remote; it’s the call syntax. He writes:

CALL FUNCTION 'Z_RFC_CREATE_PO_ASYNC'
  STARTING NEW TASK 'PO_CREATE'
  DESTINATION 'Z_RFC_VALID_DEST'
  EXPORTING ...
  .

The task name is a unique identifier. The caller can later check the status with WAIT UNTIL ... or retrieve results via a callback routine (using PERFORMING ... ON END OF TASK). He demonstrates a simple polling approach using transaction SM58.

4.2 Monitoring Asynchronous RFC with SM58

If the aRFC call fails (e.g., destination down), the request is stored in the Transactional RFC queue. Arjun opens SM58 (Transactional RFC) and shows how to resend or debug. Actually, aRFC errors go to the ARFCSSTATE table; SM58 shows these. He explains that for guaranteed delivery, you need tRFC, not plain aRFC.

5. Transactional RFC (tRFC) – Guaranteed Delivery

5.1 The Difference Between aRFC and tRFC

Transactional RFC ensures that the called function module is executed exactly once (exactly‑once semantics). It stores the function call parameters in the database (ARFCSSTATE) and uses a background scheduler to deliver and execute. If the target system is unavailable, the call remains in the queue and is retried until successful. This is essential for mission‑critical data where duplication is unacceptable.

Arjun wants the e‑commerce portal to be able to send a PO creation request via tRFC, guaranteeing that even if SAP is temporarily unreachable, the PO will be created when SAP is back. He modifies the previous aRFC function to be invoked via CALL FUNCTION ... IN BACKGROUND TASK. Actually, tRFC uses CALL FUNCTION ... IN BACKGROUND UNIT in ABAP. He creates a wrapper that the portal’s integration server (like SAP PO or directly via NCo) can call as a tRFC client. He shows the ABAP side:

CALL FUNCTION 'Z_RFC_CREATE_PO_T'
  IN BACKGROUND TASK
  DESTINATION 'NONE'
  EXPORTING ...

The function module is then executed by the background work process. Monitoring is done via SM58. He demonstrates how to configure the tRFC options in SM59: gateway, program ID, etc. He also shows the ARFC_RUN report to process queues.

6. Queued RFC (qRFC) – Ordered Processing

6.1 The Need for Sequence

Suppose the portal needs to create a PO and then later send an update to the same PO. Using plain tRFC, these two calls might be executed out of order if they end up in different queues. qRFC ensures that calls within the same queue are processed sequentially. Arjun explains the concept: a queue name is assigned, and all calls with that queue are processed in the order they were created.

He creates a qRFC scenario: the portal sends a PO creation and then an immediate confirmation. Both are placed in queue PO_2000. Even if the creation takes longer, the confirmation will wait until the creation is done, preventing status inconsistencies.

Configuration: Transaction SMQ1 (qRFC Monitor – Outbound Queue) and SMQ2 (Inbound Queue). He shows how to register the queues and activate the qRFC scheduler. He doesn’t go deep into configuration, but gives the functional overview and when to use it.

7. Calling RFC from an External System – Python Example with pyrfc

7.1 Setting Up pyrfc

Arjun demonstrates a Python script on his local machine. He installs pyrfc from PyPI (pip install pyrfc) and uses the SAP NetWeaver RFC SDK (NCo). He shows the connection parameters: ashost, sysnr, client, user, passwd. Then:

from pyrfc import Connection
conn = Connection(ashost='sapserver', sysnr='00', client='200', user='RFCUSER', passwd='password')
result = conn.call('Z_RFC_CHECK_PO_LIMIT',
                   IV_LIFNR='0000002000',
                   IV_EKORG='1000',
                   IV_NETWR=120000,
                   IV_WAERS='USD',
                   IV_DATE='20260101')
print(result['EV_VALID'], result['EV_MESSAGE'])
conn.close()

He runs the script and the terminal shows False and the error message. This confirms the external portal can validate prices in real time. He notes that in production, secure authentication (like SNC or certificates) would be used.

Screenshot Description: Terminal showing the Python script execution with the result.

8. Debugging RFC – Connecting the Dots

8.1 External Breakpoints for RFC User

Arjun needs to debug the RFC function when called from the external system. He sets an external breakpoint in SE37 for the function module, specifying the RFC user. When the Python script invokes the RFC, the ABAP debugger pops up in his SAP GUI session. He can step through the code. This is a crucial technique for troubleshooting integration issues.

8.2 Analyzing RFC Traces with ST05 and SM58

If the RFC fails silently, he uses ST05 to trace the SQL statements of the RFC user. SM58 shows any stuck tRFC calls. He also uses SRT_MONI for web services, but for RFC, the combination of SM58, SMQ1, SMQ2, and the system log (SM21) is key.

9. Complete Hands-On Lab – Building the Validation RFC End‑to‑End

Arjun now documents a comprehensive lab that covers everything:

  1. Create function group ZFG_PURCH_VALID in SE37.
  2. Create remote‑enabled function module Z_RFC_CHECK_PO_LIMIT with the interface and code as above.
  3. Activate and test in SE37.
  4. Create RFC destination Z_RFC_VALID_DEST in SM59 for ABAP connection (even to same system).
  5. Write an ABAP report that calls the function module via RFC and displays the result.
  6. Install pyrfc (if environment available) or simulate external call via wget to a web service wrapper (out of scope). But Arjun demonstrates the Python call using a pre‑configured environment.
  7. Implement a tRFC wrapper for PO creation and explain the queue mechanics.
  8. Use SM58 to monitor the tRFC calls and manually execute if stuck.
  9. Debug the RFC using external breakpoint.
  10. Document performance implications: each RFC call has overhead; batch calls when possible.

10. Best Practices, Pitfalls, and Alternatives

  • Stateless design: Keep RFC function modules stateless unless you fully control the session life cycle. Use import parameters instead of global data.
  • Security: Use dedicated RFC users with minimal authorizations. Never use dialog users. Consider SNC for encryption.
  • Error handling: Always raise proper exceptions and provide clear messages. The caller must handle sy-subrc or exceptions.
  • Avoid long-running RFC: Synchronous RFC holds a work process; timeouts can cause issues. Use aRFC or tRFC for longer tasks.
  • Batch RFC: For high‑volume scenarios, consider batching multiple calls or using a single function that processes a table of inputs (e.g., check multiple POs at once).
  • Alternatives: OData (covered in Part 38) is the modern synchronous API. RFC is still used for internal system‑to‑system and legacy integration. For new APIs, OData or SOAP web services are preferred. However, for high‑performance internal SAP‑to‑SAP, RFC still rules.

11. Conclusion – The Integration Layer Is Yours

Arjun’s RFC function module is now live, serving the e‑commerce portal with real‑time validation. The tRFC mechanism ensures PO creations are never lost. He has connected the SAP backend to the outside world using a technology that has been the backbone of SAP integration for decades, and he has future‑proofed it by wrapping the logic in a clean, remote‑enabled module. With this knowledge, you can now build interfaces that bridge systems, reliably and securely.

Tomorrow, in Part 42, we’ll dive into ALE & IDocs — the backbone of SAP‑to‑SAP and B2B communication. You’ll configure partner profiles, set up IDoc types like ORDRSP, and even process incoming IDocs in ABAP. The integration journey continues.

Keep coding, keep connecting.

End of Part 41 – Function Modules & RFC Deep Dive. Brought to you by @FreeLearning365 and tech partner @techbook24.

Post a Comment

0 Comments