Chapter Two SAP Remote Function Call (RFC)
Before you can start with JCo programming, you need to understand the SAP architecture
to a certain extent, particularly how you can invoke SAP functionality from the outside
(client programming) and how ABAP applications can invoke your components (server
programming).
The basis for all communication between SAP and external components (as well as for
most communication between SAP components) is the Remote Function Call (RFC)
protocol. RFC comes in three flavors.
Most client programs want to use regular, Synchronous RFC (sRFC), but SAP also
supports Transactional RFC (tRFC) and Queued RFC (qRFC). tRFC is used mainly to
transfer ALE Intermediate Documents (IDocs). Currently, this text covers only sRFC, but
JCo also supports tRFC and qRFC.
2.1. BAPIs and Other RFMs
ABAP Function Modules can only be called from an external client if they are marked as
RFC-enabled. R/3 contains several thousands of such RFC-enabled Function Modules
(RFMs). Amongst them are the BAPIs. BAPIs are RFMs that follow additional rules and
are defined as object type methods in SAP's Business Object Repository (BOR). Use
transaction codes BAPI and SE37 to investigate the metadata of the BAPIs and other
RFMs in SAP. If you do not have access to an SAP system, or you want to look up
interfaces in a different release, use the SAP Interface Repository
(http://ifr.sap.com).
An RFM can be released for customer use or not.(Actually, there are three states: not released, released within SAP, released for customer use. For people
outside of SAP, the two former categories can be subsumed under unreleased.) Most BAPIs
are released RFMs, only very new ones may be unreleased at first so that SAP and the customers can test them for a while before they are released in a subsequent release.
On the other hand, there are quite a few extremely useful RFMs that are not officially released for customer use.
Many of these RFMs are not documented (or only in German), which makes it harder to
figure out exactly how they work. Additionally, SAP has reserved the right to make
incompatible changes to unreleased RFMs. Using these directly in your applications
could thus result in a huge maintenance effort. Hence all access to unreleased RFMs
must be done through components in order to limit maintenance to this one component
as opposed to potentially many individual applications.
2.2. RFC-enabled Function Modules (RFMs)
RFMs can have three types of parameters, import (the client sends these to the RFM),
export (RFM sends these back to the client), and tables (bi-directional). Import and
export parameters can be simple fields (a.k.a. scalars) or structures.(Since some time
SAP now also allows complex structures and tables as parameters. The BAPIs do not use
this capability, as far as I know (nothing is ever really certain in BAPI land). JCo supports complex parameters, but this text ignores them for now.) A structure is an
ordered set of fields.
A table parameter has one or more columns (fields) and contains zero or more rows.
Import and table parameters can be mandatory or optional, export parameters are always
optional. You can check these attributes in SAP or even at runtime.
Some people assume that table parameters are somehow magically linked to the database
tables in SAP. That is not the case. If you change a table that an RFM call returned,
nothing happens in SAP. A table is really just a form of glorified array (glorified
because we have metadata for the columns). Changes in SAP will only happen if you call
an RFMthat uses a table parameter you pass to it in order to update the database.
RFMs can also define ABAP exceptions. An ABAP exception is a string (e.g.NOT_FOUND) with
an associated language-dependent message text. We will discuss exception handling below.
2.3. The SAP Data Dictionary
In RFC programming, eventually we always deal with fields. These fields can be scalar
parameters themselves or contained in a structure or table row. Most, but not all, fields
used in RFMs are based on Data Dictionary (DD) definitions. Each field in the DD is
based on a Data Element (which in turn is based on a Domain) or a built-in DD data type.
The Domain defines the basic technical attributes (data type, length, conversion routine,
check table, etc.), whereas the Data Element contains the more semantical information
(texts and documentation).
There is a lot of metadata available for each field in SAP. I will now introduce the most
important attributes and how they affect your applications (more details can be found in
the next section):
· Data type, length, number of decimals: These are essential for dealing with fields
correctly and building nice user interfaces that are aware of the field attributes.
JCo makes these attributes available to the client program.
· Check table: Many fields contain codes. End-users do not want to deal with them, at
least not without the associated descriptions. When you call a BAPI and display the
returned country code, the users will not be happy. They need the name of the country
instead of – or together with – the code.
If users have to enter codes, they do not want to guess; they want a list of available
codes (Helpvalues) with their descriptions.
· Fixed values: This is similar to check tables, but the information about the codes is
stored in the Domain, not in a separate table.
· Conversion exit: Many fields use conversion exits in SAPGUI to translate between
the internal and external representations of data. Most BAPIs return and expect the
internal format, which makes little to no sense to your users.
· Texts and documentation: SAP stores multiple texts per field and also extended
documentation in many cases. This documentation is available in all installed
languages and therefore an easy way to provide multi-lingual capabilities in your
applications.
· Mixed case support: Many text fields in SAP are uppercase only. If users exercise
care in entering data in mixed case, they will not be too happy to discover later that
everything was capitalized in SAP. Your user interface should exploit the mixed case
attribute to indicate to the users which fields are uppercase only.
The ARAsoft JCo Extension Library allows easy access to all the required metadata that
JCo does not expose. The library also offers services that solve all the practical
problems associated with the metadata,including Helpvalues, conversions, text retrieval.
See below for details.
2.4. BAPI Specifics
As stated above, a BAPI is an RFM that follows additional rules (defined in the SAP
BAPI Programming Guide5) and is defined as a method of an object type in the BOR. An
example for a BAPI, as defined in the BOR, is SalesOrder.CreateFromDat1. The actual
RFM implementing this BAPI is BAPI_SALESORDER_CREATEFROMDAT2. When comparing the metadata shown by the BAPI Explorer (transaction code BAPI) and those in the Function Builder (transaction code SE37), you will notice that there can be discrepancies like different parameter names. When writing your actual application code,you need to use the names presented by the Function Builder. It is best to use the BAPI Explorer just as a convenient starting point to find suitable BAPIs and then review the actual metadata of the RFM in the Function Builder (unless you use proxies, see below).
The BOR presents certain attributes not available in the Function Builder:
· Is the BAPI obsolete? When SAP wants to change a BAPI in a way that would be incompatible
with the existing version, they create a new BAPI instead, e.g. Create1 would be the new
version of Create. The old BAPI becomes obsolete. An obsolete BAPI is guaranteed to exist
and work in the release in which it is marked as obsolete and the subsequent functional
release. For example, a BAPI made obsolete in 4.0A would still be valid in 4.5B (the
maintenance release for the functional release 4.5A),but might disappear in 4.6A.
· Is the BAPI released? Checking this is of utmost importance. SAP sometimes creates
new BAPIs without releasing them yet. Only released BAPIs are guaranteed to be
upward-compatible, though, so you should only use unreleased BAPIs if you have no
other choice.
· Does the BAPI pop up SAPGUI dialogs? These BAPIs were built mainly for the communication
between SAP components, they rarely make any sense in a Java application. SAPGUIs are
difficult to pop up from a web application running in a browser…
If you want to use BAPIs in a more object-oriented way, you need to utilize proxy classes. These proxies have the following advantages:
· A business object type in the BOR is represented by one Java class, the BAPIs are
methods of the class.
· Instead of the somewhat ugly function and parameter names in the SAP Function Builder
you use the nice names in the BOR.
· You can exploit additional BOR metadata. One example is that the BOR knows which table
parameters are import, which are export, and which are import and export. The Function
Builder has no notion of this.
· You can use an easy request/response programming model. Instead of dealing with
three parameter categories, viz. import, export, and tables, you simply have request
and response parameters.
· You can use the Code Completion/Code Insight/Intellis*nse features of your Java IDE and
do not have to type hard-coded function and field names like with native JCo.
· You can generate proxies that optionally exclude those BAPIs that are obsolete, not
released yet, or that pop up SAPGUI dialogs.
All of these advantages do not imply that you have to use proxies. Many people
(including myself) are perfectly happy with native JCo. If on the other hand, you like the
idea of using proxies, please turn to Appendix A-7.
When using BAPIs in your applications, you must also be aware of some idiosyncrasies
(some of them were introduced briefly in the section dealing with the SAP Data Dictionary). They are discussed in the following sections.
2.4.1. Conversions
BAPIs mostly use the internal representation of codes. One of the more famous examples
is units of measurement: A SAPGUI user logged on in English will type PC (piece) as a
unit while the BAPIs use the internal (German) representation ST. Another example is
customer numbers. A customer number can contain letters, but if it consists of digits
only, it is internally stored with leading zeroes. The user wants to neither see nor
have to enter these leading zeroes.
SAPGUI automatically performs the necessary conversions so that its users always see
the external representation. This is possible since for each Domain a conversion routine
(sometimes called a conversion exit) can be defined if appropriate. This exit is called
both inbound (the user enters data to be passed to the application) and outbound (the
application returns data to be displayed in SAPGUI). Data originating in the application
is converted from the internal to the external format; data entered by the user is first
validated and then converted from the external to the internal format.
The fact that, in SAPGUI, the conversion exits are always called automatically has been a
source of confusion for many developers who wanted to try out a BAPI in SAP's Function Builder (transaction code SE37) in order to learn more about the BAPI's parameters. If you run the SalesOrder.CreateFromDat2 (RFM BAPI_SALESORDER_CREATEFROMDAT2) BAPI inside SAP, for example, and enter the document (sales order) type as OR (for a standard order), all works well. If, on the other hand, you use the same code from outside of SAP, you will receive an error message telling you that you have used an invalid code.
This is due to the fact that even the very technical test environment of the Function
Builder uses the conversion exits. But the BAPI itself does not invoke them. Many developers in this situation end up hard-coding the German equivalent of OR (TA) in their programs. That may be acceptable for a quick-and-dirty demo program, but software for production use should avoid hard-coding constants that are subject to SAP customization.
Also, conversions are required for many other parameters, and it would definitely be
better to have a generic solution. The ARAsoft JCo Extension Library (see below)
automates the necessary conversions for you, but you can use the conversion BAPIs found on object type BapiService if you want to build your own component dealing with conversions.
2.4.2. Helpvalues
The BAPIs return lots of codes. When you invoke Customer.GetDetail, for example, you get back, amongst other information, the code of the country in which this customer resides. Users do not really remember what all the codes stand for, though. They want text (the code's description) in addition to, or even instead of, the code. Along the same lines,
when a user has to enter a code (e.g., a country code when adding a new customer), it would be nice if we offered a drop-down combo box with all available choices (showing the text by itself or the code and the text) instead of a plain text box where the user has to guess the correct code.
In some cases, SAP offers suitable BAPIs to retrieve the required information.
CompanyCode.GetList and GetDetail offer a list of all company codes with associated
descriptions and detailed information for one company code, respectively.
In most cases, though, we are not that lucky. There is no Country object type, for
instance. The Helpvalues object type provides BAPIs that can help us to deal with those
entities for which there is no object type in SAP. To figure out whether there is
Helpvalues support for a given entity, you must verify whether a check table or a fixed
values list is defined for the field (DDIF_FIELDINFO_GET allows you to do this at
runtime, but you can also look it up in the DD when you build your application).
Unfortunately, the Helpvalues BAPIs are hard to use and, to make matters worse, they
return different results in different SAP releases. The BAPIs are also relatively slow, so it is imperative that we make as few calls to them as possible and cache the results.
To complicate matters further, some of the entities form hierarchies. Countries, for example,contain regions (states, provinces, Kantone, Bundesländer). There are even
multi-level hierarchies (e.g., Sales Organizations containing Distribution Channels containing Divisions containing Sales Offices). You clearly need a component to deal with all these issues. If you want to avoid having to build the required component, take a look at the ARAsoft JCo Extension Library (see below) which takes care of all the necessary
processing.
2.4.3. BAPI return messages
All BAPIs are supposed to use a RETURN parameter instead of throwing ABAP exceptions.6 After each BAPI call, you should7 check the message that came back from SAP to see whether the BAPI call was successful. You have to be very careful here,though, since different BAPIs use different structures with different field names for the RETURN parameter.
The ARAsoft JCo Extension Library contains a class (BapiMessageInfo) that hides these
inconsistencies from the developer and also allows easy access to the documentation for a
BAPI message.
2.4.4. Currency amounts
Internally, SAP uses data type CURR to represent currency amounts. CURR is a packed
number (or Binary Coded Decimal, if you prefer) with two decimals. How are currencies
that use a different number of decimals stored? In order to be able to store large amounts
in currency fields, SAP shifts the amount so that the last digit of the value is stored in the second decimal position. Two Japanese Yen, for example, are stored as 0.02, which is
wrong by a factor of 100. SAP internally knows how to handle this and converts the
amounts as required before displaying them. In order to avoid that extra effort for BAPI
client programmers, SAP decided not to use data type CURR in BAPIs. Instead, the BAPI
Programming Guide states: "All parameters and fields for currency amounts must use the
domain BAPICURR with the data element BAPICURR_D or BAPICUREXT with the data element BAPICUREXT." Not all BAPIs follow the rules, though. Always doublecheck that the BAPI currency amount fields you use in your applications follow the rules.
Otherwise, you need to correct the value yourself, or let the ARAsoft JCo Extension
Library do it for you (method getCorrectAmount() of class JCoRepository).
2.4.5. Delegation
The Business Object Repository supports a concept called Delegation. This is used when
you subclass an object type and overwrite one or more of the BAPIs to enforce your own
business rules. If an SAP object type is delegated to one of its subclasses, you should
always call the RFM defined in the subclass instead of the standard SAP one.
If your company uses Delegation, or you want to sell your product to a customer who
does, you should always determine the name of the correct RFM by using some kind of
properties file or looking up the correct name dynamically using metadata access
services. In order to avoid having to build your own metadata component, you could use
the ARAsoft Java BAPI ObjectFactory that comes with the ARAsoft JCo Extension
Library.
posted on 2005-12-01 10:38
Dr.Magic 阅读(1993)
评论(1) 编辑 收藏