SAP Adapter – No “BAPI” node in the Metadata Search/Browse hierarchy when creating an “Inbound” contract?

A question which has popped up quite a few times over the last couple of weeks – “For an outbound contract, I see RFC, TRFC, IDOC and BAPI nodes in the UI. However, for an inbound contract, the BAPI node is missing. Why?”

Firstly, I’m going to explain what each of the four nodes you see really translate to within the adapter, and how they are “transported” to SAP.

The adapter communicates with SAP using the RFC protocol (it uses the RFC SDK for this purpose – which is written in C). RFC stands for “Remote Function Call” – a mechanism for calling Function Modules (functions) on SAP from external systems (you can also have functions defined on SAP which are not enabled for remote access). Using the RFC SDK, an external client can either invoke a RFC on SAP (outbound calls), or listen for incoming function calls (inbound).

The RFC and TRFC nodes you see in the metadata UI, are the only *pure* manifestations of this in the adapter.

Under the RFC node, we display all the function modules (which have been configured on SAP to allow them to be called from an external client). Invoking an operation under this node – the adapter just turns around and invokes that same operation on SAP.

The same functions also appear under the TRFC node. TRFC stands for “Transactional Remote Function Call”, though it is not really transactional. When you invoke an operation which appeared under the TRFC node (the Action is different for the same function under the RFC and TRFC nodes), the adapter when invoking the function on SAP, associates an identifier with the call. the SAP server makes a note of this identifier, and maps it to the execution status of that function. If, (suppose), the SAP server went down before completion of the function execution, the client can, at a later point, re-execute that call with the same identifier. SAP will realize that this call hasn’t been made before, and will attempt to re-execute the function. On the other hand, if SAP had successfully completed the call earlier, but if the client went down before it could process the response (or a network failure occurred before it could receive the response), the client can, at a later point, re-execute that call with the same identifier. SAP will know that an earlier call with the same identifier already completed successfully earlier, and will not execute it again, but will just send a response back to the client. The client, when it gets back a response (either on the first or later retries) should then clean up its own state with respect to the identifier, and also instruct SAP to do the same (via a RFC SDK API call, which the adapter exposes as an operation named “RfcConfirmTransID”). Once this cleanup/confirmation happens, this identifier is “forgotten”, and the next time this identifier is seen, it is assumed to be a brand new identifier / operation call. NOTE that in a TRFC call, SAP does not return any output values – hence the difference in the operation signatures when you compare them for the same RFC under the RFC node compared to the TRFC node.

What about the operations under the IDOC node? Sending IDOCs to SAP requires the client (the adapter) to execute special RFCs named IDOC_INBOUND_ASYNCHRONOUS / INBOUND_IDOC_PROCESS (depending on the version) on SAP. Receiving IDOCs from SAP requires the external application (now acting as the server) to be able to handle incoming calls to the same two functions. Operations under the IDOC node in the adapter are hence “dummy” operations which the adapter exposes – the adapter gets metadata for all available IDOCs on the SAP system, and exposes “Send” and “Receive” calls with different complex parameters based on the IDOC you want to work with. At runtime, for outbound calls, the adapter takes the individual pieces of data and converts them to the format which the above mentioned two RFCs require. For inbound calls, it splits/parses the data which it received from SAP as incoming parameter values to the above two RFCs, looks at the data to figure out which IDOC is being transmitted, gets metadata for that IDOC, and then re-formats the data to fit that metadata.

Note – for inbound IDOC calls, the adapter exposes a property named ReceiveIdocFormat (which is an enumeration of type IdocReceiveFormat). One of the values in this enumeration is “Rfc” – if you choose this, then, for incoming IDOCs, the adapter won’t peek at the data to figure out which IDOC it is and re-format it to fir the “Receive” operation – instead, it will just expose it as a RFC call to the servicehost – as a call to IDOC_INBOUND_ASYNCHRONOUS / INBOUND_IDOC_PROCESS. Well, actually, it will expose it as a TRFC call (i.e. the WCF message will have the TRFC action) since when SAP sends IDOCs to an external application, it usually does that using transactional semantics – at least SAP’s mechanism of transactions. (Note - the default value of the property/enumeration is “Typed”).

Lastly, **BAPI**s. SAP allows you to create Business Objects, and with each object, associate methods, events, attributes, etc – its version of OOP. In the current SAP architecture, methods on business objects are just RFCs. Hence, at design time, the adapter looks up the Business Object Repository (BOR), and determines the objects present on SAP. For each object, it figures out what methods were defined for it, and what the actual implementation is – that is, what is the actual RFC to which it maps. The adapter then shows the friendly names of the operations in the UI (since it has that information when it looked up the BOR), but in the Action , it actually uses the RFC name – since at runtime, what it really needs to do is just execute the corresponding RFC.

And now, coming to the question which this post was meant to answer – why is there no BAPI node in the UI for an inbound contract? When the adapter receives an incoming call from SAP, all it has is the function name – since after all, as you can see above, everything just involves execution of an RFC – for both outbound and inbound calls. If SAP sent along a “transactional” identifier with the function invocation, the adapter formats the incoming message (which it gives to the WCF service / BizTalk Receive Location) as a TRFC call. If the function which SAP invoked was named IDOC_INBOUND_ASYNCHRONOUS / INBOUND_IDOC_PROCESS, the adapter recognizes these functions as “special”, and peeks at the data to determine the IDOC being transmitted, and formats the WCF message as a call to “Receive” with the appropriate action (which contains the IDOC type, among other things). Else, the incoming WCF message is now just formatted as a call to an RFC (with the Action containing the RFC name).

The adapter can’t format the WCF message using an Action corresponding to a specific Business Object (i.e., corresponding to an operation that would live under the BAPI node), since strictly speaking, there is no mapping from the RFC name to the Business Object type which implements it. The BAPI node in the UI for outbound contracts was really more of a convenience mechanism – so that a user can navigate the business object hierarchy to find the function of interest. All functions under the BAPI node also appear under the RFC and TRFC nodes too. For inbound calls, if you’re interested in listening for an incoming function like BAPI_SALESORDER_CREATE (which is most probably a function with the friendly name “Create” defined on the “SalesOrder” business object), just search for the RFC named BAPI_SALESORDER_CREATE under the RFC node (or under the TRFC node if you know that SAP is going to execute this “transactionally”). NOTE that in the most common case, only the “special” IDOC RFCs are invoked transactionally by SAP on an external application, so for all other incoming RFC calls, you should just add the operation under the RFC node to your Service Contract.