Having been around the SAP Universe for a few years, the idea of calling a SAP function module remotely (or RFC) wasn’t a new topic at all. I would imagine that most ABAPers know about the magic radio button labeled Remote-enabled module on the Function Builder Attributes tab. This wonderful option is about all it takes to expose your function to any tool capable of communicating with SAP. The only other thing to keep in mind is to mark all your parameters as Pass by Value. Even at that you don’t have to remember. The editor will yell at you if you forget. Also keep in mind that what SAP calls a BAPI is really just an RFC. BAPIs are linked to a business object and usually have additional documentation, but from a technical standpoint they are just plain RFCs.
RFCs are incredibly easy to call from ABAP. All you have to do is add the Destination parameter to the call. For anyone who might never have seen an RFC in use here you go:
call function 'Z_E_RFC_FIELD_DESCRIPTINS' destination 'DEV' exporting rollname = 'CVFLAG' language = sy-langu importing ddtext = currv_desc.
Wow this is all so incredibly easy. What in the world am I going to write about? Wait – don’t worry. It doesn’t take long to run into the first problem.
It is easy to call an RFC from within an R/3 system. You will have all the data elements and structures necessary to define the importing and exporting parameters. Oops – I knew we were missing something! Our standalone WebAS didn’t have most of these same data elements and structures since it was the technology stack only. And it certainly didn’t have any customer created elements unless we copied them over to the WebAS. Of course we could always create all the missing elements by hand, but as developers we have a long tradition of work avoidance to live up to. It would be great if SAP had a tool that would read the exporting/importing parameters on an RFC and generate the necessary data statements for us.
Well we were in luck. There is just such a tool. It is called the BAPI Browser.
This great little tool can be accessed from within SE80. If you are editing a BSP application and are in a Page or View, you can launch the BAPI Browser from the menu via Goto -> Bapi Browser or Ctrl+Shift+F1. You can then browse though a list of BAPIs for an RFC destination (hence the name) or do a Direct Entry search for any RFC enabled function. As you can see from my screen shot you get all the data declarations you need in addition to a sample call of the function module. The main draw back is that if the function interface changes, you have to rerun the BAPI Browser and change the declarations manually. In my next weblog I will discuss using XML to get around this little problem. Also if anyone from SAP is reading this, I have a suggestion for the BAPI Browser: I would like to be able to launch it from anywhere in SE80, not just BSP coding. Quite often I am coding inside a Model or Application class and that is where I need to call my BAPI. However I have to switch back to a BSP View or Page to activate the tool.
I should note that SAP actually delivered a lot of the most important data elements with one of the early support packages. Even though this is a technology system only, you can now find such elements as MATNR (Material Number) and WERKS_D (plant) just to name a few. This makes your work easier but there are still plenty of elements missing in order to need the BAPI Browser.
Now that we are off and calling our RFCs everything is fine, right. Well until the calling system isn’t available, or the RFC destination is setup wrong, or the user isn’t authorized for the activity, or any other of a number of things that might go wrong. Normally these activities will create a nice short dump. However from a BSP page, the short dump doesn’t really make for the best user experience. Wouldn’t it be nice to be able to catch all of these System-type exceptions? Well you can. Just look at the following example.
data: msg_text(80) type c. call function 'Z_E_RFC_QUERY_UG_AUTH_CHECK' destination rfcdest exceptions communication_failure = 1 message msg_text system_failure = 2 message msg_text not_authorized = 3.
As you can see here I have added two special exceptions that aren’t implicitly declared by the function itself. COMMUNICATION_FAILURE and SYSTEM_FAILURE are two exceptions that are automatically available to any function that is being called remotely. All of the types of problems I mentioned before will be trapped by these exceptions. The details of the error will be placed into a variable that you declare. In my example this is msg_test. I find that it is better to stop processing but display the details from this message back to the user rather than show the generate message.
Dynamic Selection of Destinations
I have just one final learning that I wanted to share before I close out this weblog. Overtime we found that it was becoming a maintenance nightmare to maintain RFC Destinations. You either end up creating a RFC destination for each application in each system or you end up hard coding destinations. Neither option ends up being very flexible. We decided to create a table where we could hold the name of the function module and the associated RFC destination. This way we could easily have different destinations maintained in each system in our landscape. The following is what our usual RFC call actually looks like:
select single rfcdest from zes_rfc_dest into rfcdest where name = 'Z_E_RFC_DOC_SEARCH'. call function 'Z_E_RFC_DOC_SEARCH' destination rfcdest exceptions communication_failure = 1 message msg_text system_failure = 2 message msg_text not_authorized = 3.
I hope that everyone enjoyed this first look at RFCs. As I have already hinted, my next weblog will still look at RFC and how we can use XML with them.