Server scenario

In Server scenario, ABAP system is calling Python remote enabled RFC server, to consume Python functionality. Python functionality must be exposed like an ABAP function module and Python server shall provide input / output parameters just like ABAP function module.

To streamline that process, the real ABAP function module is used as a “blueprint” and Python server will create exactly such ABAP interface to expose Python functionality.

When Python server function “ABC” for example is registered on Python server, the name of ABAP “blueprint” function module is given, where the input/output parameters definition shall be taken from. Let use ABAP function module “XYZ” for this example. The Python server will fetch ABAP function module “XYZ” definition and expose Python function using ABAP function module input/output parameters. The ABAP logic of “XYZ” is here irrelevant, the function module can be empty. Already existing or new ABAP function module can be used to define Python function interface.

Python RFC server shall run in separate thread, created automatically by PyRFC, or created by Python application.

Server in thread created by PyRFC

Server running in new thread created by PyRFC is started using start() method:

# create server

and can be stopped using close() method:

# shutdown server
server.close()

Example: server_pyrfc_thread.py

Server in thread created by application

Here the PyRFC server is registered for ABAP system gateway and Python function my_stfc_connection is exposed input/output parameters like ABAP function module STFC_CONNECTION.

def my_stfc_connection(request_context=None, REQUTEXT=""):
    """Server function my_stfc_connection with the signature of ABAP function module STFC_CONNECTION."""

    print("stfc connection invoked")
    print("request_context", request_context)
    print(f"REQUTEXT: {REQUTEXT}")

    return {
        "ECHOTEXT": REQUTEXT,
        "RESPTEXT": "Python server here",
    }

Server is created and started in Python function launch_server() and this function is invoked in new thread started by application:

def launch_server():
    """Start server."""

    # create server for ABAP system ABC
    server = Server(
        {"dest": "gateway"},
        {"dest": "MME"},
        {"check_date": False, "check_time": False, "port": 8081, "server_log": False}
    )
    print(server.get_server_attributes())

    # expose python function my_stfc_connection as ABAP function STFC_CONNECTION, to be called by ABAP system
    server.add_function(
        "STFC_CONNECTION",
        my_stfc_connection,
    )

    # start server
    server.serve()

    # get server attributes
    print(server.get_server_attributes())


server_thread = Thread(target=launch_server)
server_thread.start()

input("Press Enter to stop server...")  # WPS110

and stopped by application:

input("Press Enter to stop server...")  # WPS110

# stop server
server_thread.join()
print("Server stoped")

Example: server_app_thread.py

Source code of ABAP test reports, calling RFC function modules exposed by Python server: z_stfc_connection_call.abap and z_stfc_structure_call.abap

Background RFC (bgRFC) Server

Configuration

Configure RFC destination using SM59 transaction

  • TCP/IP Connection NWRFC_SERVER_OS

  • Special Options > Select Protocol: basXML serializer

basXML serializer shall be configured for RFC server destination in SM59 transaction

_images/sm59-serializer.png

Configure bgRFC queues using SBGRFCCONF transaction

Scheduler app server and destination

_images/SBGRFCCONF-Scheduler-App-Server.png

Scheduler destination

_images/SBGRFCCONF-Scheduler-Destination.png

Configure inbound destination prefixes for bgRFC queues’ names. Other queue names are processed as standard RFC queues.

_images/SBGRFCCONF-Define-Inbound-Destination.png

bgRFC Client

To test sending bgRFC queue to ABAP system, you can try the example bgrfc_client.py , adapted to your system,

python examples/server/bgrfc_client.py MME

from pyrfc import Connection

client = Connection(dest=sys.argv[1])

unit = client.initialize_unit()

name = "BGRFC_TEST_OUTIN"
counter = "00001"

client.fill_and_submit_unit(
    unit,
    [("STFC_WRITE_TO_TCPIC", {"TCPICDAT": [f"{name:20}{counter:20}{unit['id']:32}"]})],
    queue_names=["RFCSDK_QUEUE_IN"],
    attributes={"lock": 1},
)

Check bgRFC queue status using SBGRFCMON - bgRFC Monitor transaction

Deleting the unit lock will release the unit for immediate execution

_images/SBGRFCMON1-Client-MME.png _images/SBGRFCMON2-Client-MME.png

bgRFC Server

For bgRFC server configuration and implementation, first check the section 5.6 Queued and Background RFC Server of SAP NWRFC SDK 7.50 Programming Guide

In addition to standard server, the bgRFC server requires the implementation of bgRFC event handlers, as per example bgrfc_server.py Event handlers shall be registered before server has started:

# create server
server = Server(*BACKEND[backend_dest])
print(server.get_server_attributes())

try:
    # expose python function stfc_write_to_tcpic as ABAP function STFC_WRITE_TO_TCPIC, to be called by ABAP system
    server.add_function("STFC_WRITE_TO_TCPIC", stfc_write_to_tcpic)

    # register bgRFC handlers
    server.bgrfc_init(
        backend_dest,
        {
            "check": onCheckFunction,
            "commit": onCommitFunction,
            "rollback": onRollbackFunction,
            "confirm": onConfirmFunction,
            "getState": onGetStateFunction,
        },
    )

    # start server
    server.start()

    input("Press Enter key to stop server...\n")  # WPS110

    # stop server and database
    server.stop()

finally:
    # clean-up the server
    server.close()

To test, first start the Python server

python examples/server/bgrfc_server.py ALX

[2023-03-28 12:16:13.215013 UTC] Server connection '5175819264'
{'serverName': '', 'protocolType': 'multi count', 'registrationCount': 0, 'state': 'RFC_SERVER_INITIAL', 'currentBusyCount': 0, 'peakBusyCount': 0}
[2023-03-28 12:16:13.577820 UTC] Server function installed 'STFC_WRITE_TO_TCPIC'
[2023-03-28 12:16:13.578015 UTC] Server function installed '{'func_desc_handle': 5166353136, 'callback': <function stfc_write_to_tcpic at 0x1007f2020>, 'server': <pyrfc._cyrfc.Server object at 0x1008b81d0>}'
[2023-03-28 12:16:13.645304 UTC] Server 'launched 5175819264'
Press Enter key to stop server...

Then run ABAP test report z_nwrfc_server_bgrfc.abap to create outbound bgRFC queue in ABAP system

_images/z_nwrfc_server_bgrfc.png

After pressing the Execute button, the server log in Python system shell continues with

bgRFC:onCheck handle 5175859712 tid FA163E82B1991EDDB3AC6EB2628DE0F1 status created
[2023-03-28 12:24:27.128859 UTC] metadataLookup 'Function 'STFC_WRITE_TO_TCPIC' handle 5166353136.'
[2023-03-28 12:24:27.130577 UTC] genericHandler 'User 'BOSKOVIC' from system 'ALX', client '000', host 'vmw6265.wdf.sap.corp' invokes 'STFC_WRITE_TO_TCPIC''
[2023-03-28 12:24:27.130621 UTC] authorization check for 'STFC_WRITE_TO_TCPIC' '{'call_type': <UnitCallType.background_unit: 3>, 'is_stateful': False, 'unit_identifier': {'queued': True, 'id': 'FA163E82B1991EDDB3AC6EB2628DE0F1'}, 'unit_attributes': {'kernel_trace': False, 'sat_trace': False, 'unit_history': False, 'lock': True, 'no_commit_check': False, 'user': 'BOSKOVIC', 'client': '000', 't_code': 'SE38', 'program': 'Z_NWRFC_SERVER_BGRFC', 'hostname': 'ldai1alx_ALX_18', 'sending_date': '20230328', 'sending_time': '122427'}}'
server function: stfc_write_to_tcpic tid: FA163E82B1991EDDB3AC6EB2628DE0F1 call: 0 {'call_type': <UnitCallType.background_unit: 3>, 'is_stateful': False, 'unit_identifier': {'queued': True, 'id': 'FA163E82B1991EDDB3AC6EB2628DE0F1'}, 'unit_attributes': {'kernel_trace': False, 'sat_trace': False, 'unit_history': False, 'lock': True, 'no_commit_check': False, 'user': 'BOSKOVIC', 'client': '000', 't_code': 'SE38', 'program': 'Z_NWRFC_SERVER_BGRFC', 'hostname': 'ldai1alx_ALX_18', 'sending_date': '20230328', 'sending_time': '122427'}}
TCPICDAT: [{'LINE': 'BASIS_BGRFC_OUTIN   00001               12345678901234567890123456789012'}]
bgRFC:onCommit handle 5175859712 unit {'queued': True, 'id': 'FA163E82B1991EDDB3AC6EB2628DE0F1'}
bgRFC:onConfirm handle 5175859712 unit {'queued': True, 'id': 'FA163E82B1991EDDB3AC6EB2628DE0F1'}

After pressing Enter button in Python system shell, recorded events are shown, recorded in tlog.log

2023-03-28 12:24:27.127087 FA163E82B1991EDDB3AC6EB2628DE0F1 created
2023-03-28 12:24:27.130816 FA163E82B1991EDDB3AC6EB2628DE0F1 executed stfc_write_to_tcpic
2023-03-28 12:24:27.132676 FA163E82B1991EDDB3AC6EB2628DE0F1 committed
2023-03-28 12:24:27.224103 FA163E82B1991EDDB3AC6EB2628DE0F1 confirmed

Unit status management and log example is provided in TLog class in tlog.py script and can be tested like:

python examples/server/tlog.py

True
{'utc': '2023-03-28 12:32:35.064000', 'tid': '60819ABA77594C698E98D552951A8A3B', 'status': 'executed', 'note': 'python_function_module'}

6
2023-03-28 12:24:27.127087 FA163E82B1991EDDB3AC6EB2628DE0F1 created
2023-03-28 12:24:27.130816 FA163E82B1991EDDB3AC6EB2628DE0F1 executed stfc_write_to_tcpic
2023-03-28 12:24:27.132676 FA163E82B1991EDDB3AC6EB2628DE0F1 committed
2023-03-28 12:24:27.224103 FA163E82B1991EDDB3AC6EB2628DE0F1 confirmed
2023-03-28 12:31:38.743892 41C5E22EB6D345EDBA8D8FBCD9F3EDE9 created
2023-03-28 12:31:38.744026 41C5E22EB6D345EDBA8D8FBCD9F3EDE9 executed python_function_module