New developments in Netweaver RFC communication
During the last one or two years, a couple of new features have been added to the RFC communication protocol. In this blog I will describe for which release they were added to the SAP kernel, and how they can be used by external programs, with a focus on the NetWeaver RFC Library, which is going to support these new features starting with release 7.20. Development of that library is getting started now, so this blog will continuously grow as we go along.
Background Communication (bgRFC)
The standard qRFC protocol has a couple of shortcomings like a high/aggressive usage of resources (work processes), a danger of running into deadlocks when queues become blocked and a certain inflexibility that makes it difficult to use for a wide variety of scenarios. (In fact in the past qRFC has been “mis-used” for quite a number of use cases for which it was not designed, leading to problems like performance bottlenecks, resource starvation, deadlocks.)
To overcome these shortcomings, a new kind of asynchronous RFC communication has been developed in SAP kernel 7.10, which provides the semantics for executing logical units of work “exactly once” or “exactly once in order”: the so-called bgRFC protocol. With enhancement pack 2, bgRFC is planned to be downported to SAP kernel 7.01, and starting with NW RFC Library release 7.20 external programs will also be able to use it.
Starting with SAP kernel 7.10, remote-enabled function modules may throw “real” ABAP OO exceptions instead of the well-known classic exceptions. A remote system can catch these exception objects and query their attributes. (Remotely invoking the exception object’s methods is not yet possible, however. That will be a next step in the direction of a true “remote method invocation concept”.)
The NW RFC Library 7.20 will also enable external C programs to catch these ABAP exception objects and query their attributes (if the external program is the client) or to create an exception and throw it back to the ABAP system (if the external program is the server).
Communication via basXML
Another feature of the 7.10 kernel is communication via a new serialization format, basXML. It was meant to provide a more efficient and unified format for function modules that use many complex and nested structures and tables as their importing and exporting parameters. If a function module specifies in its attributes, that it wants to use basXML serialization, and if that feature is available on both communication partners (a switch in the RFC destination in SM59 is necessary here), then the complete payload will be serialized in the new format.
The NW RFC Library already supports this format right from the first release 7.10. You as the application programmer should not notice much of a difference here, as this is handled “under the hood”. The only noticable difference should be a slight change in performance: slightly worse performance, if the function module in question has only standard “flat” parameters (in this case basXML should be turned off), and slightly better performance for function modules with many complex parameters.
Update on recent features
Meanwhile the first two patch levels of NW RFC SDK 7.20 have been released to public, and they brought quite a number of fixes and improvements. A complete list is given in the notes 1511382 and 1511433. Here I just want to highlight a few features which I think will be very beneficial for RFC applications.
Performance improvement for DDIC lookups in the backend.
In previous releases, an external program had to perform one roundtrip for every function module plus one additional roundtrip for each structure/table that this function module was referencing. If a program is using 5 different FMs with 10 structures/tables each, this sums up to 50 roundtrips to the backend, which costs a substantial amount of time during initialization of the program. In long running processes, which look up their metadata once in the beginning and then use it for days or even weeks, this is not a problem. However, in short-lived processes, which are started quite often, perform only a handful of RFC calls and then die again, this overhead can cost more execution time than the actual “business logic”.
To improve this situation, there is now a new DDIC lookup FM on ABAP side (RFC_METADATA_GET) and a new set of functions in the NW RFC library, which leverages this FM (RfcMetadataBatchQuery plus a few helper functions for iterating through the result set of the batch query). Using this function, you can lookup all DDIC definitions for all function modules/structures and tables that your program may need during its lifetime with one single roundtrip to the backend. See SAP note 1456826 for the prerequisites on ABAP side, and the doxygen documentation of RfcMetadataBatchQuery for how to use this feature.
For very short-lived processes that are started thousends of times in short order, even the above process might be too slow. These programs then should not lookup their metadata in the backend, but hard-code it internally instead, using the set of APIs around RfcCreateFunctionDesc,RfcCreateTypeDesc and RfcAddFunctionDesc.
Index-based access to structure/table/function module fields
Like in JCo and NCo you can now set and get field and parameter values by index instead of by name. This should be quite a performance improvement, if you have loops over big tables, where thousends of fields need to be accessed.
Information about the type of an incoming RFC call
Using the function RfcGetServerContext, you can now access some important information from inside your currently executing server function (function of type RFC_SERVER_FUNCTION): you can see, whether you are currently running in the context of a synchronous RFC call, a tRFC/qRFC or a bgRFC. In the later cases you will also get access to the TID or the Unit ID. This should make it much easier to write multi-threaded server programs that can handle tRFC/qRFC/bgRFC in such a way that they preserve “transactional security” (i.e. execution once and only once).
For example: the RFC_ON_COMMIT_TRANSACTION function needs to perform a database “commit work” exactly for the data belonging to the current TID. But in order to do this, the RFC_SERVER_FUNCTION(s) must already store the TID together with the data that it wrote into the database (or get access to the current DB connection corresponding to the current TID). Previously an RFC_SERVER_FUNCTION had no access to the current TID, so this was very difficult to achieve. (E.g. by having the RFC_ON_CHECK_TRANSACTION store the TID in thread-local storage or in a global hasmap, from where the RFC_SERVER_FUNCTION(s) could then get it. With the new RfcGetServerContext function it is now very easy to make the link-up between the current TID and the corresponding data payload processed in the various RFC_SERVER_FUNCTIONs.
More general information
Some people found the following articles about the concepts of NW RFC programming quite useful. Therefore I provide a reference to them here: