GRC
HR
SCM
CRM
BI


Article

 

BAPI Conversion Issues

by Thomas G. Schuessier | SAPinsider

January 1, 2001

by Thomas G. Schuessier, ARASoft SAPinsider - 2001 (Volume 2), January (Issue 1)
 

If you have done any serious BAPI programming, you are aware that 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¹ in the SAP Data Dictionary a conversion exit can be defined if appropriate. This exit is called both inbound and outbound. 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.CreateFromDat1 BAPI inside R/3, 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.

     Fortunately, there are special BAPIs available in SAP (since 4.0) that allow us to invoke the required conversion exits. These BAPIs are methods of object type BapiService. There is one BAPI for the conversion from external to internal (DataConversionExt2Int) and one for the conversion from internal to external (DataConversionInt2Ext). Improved versions (the names of which end with "1") have been added in recent releases. The conversion BAPIs call the same conversion exits used in SAPGUI.²

Conversion Exits Considered Harmful

In this article I want to draw your attention to a potential problem when using the conversion BAPIs: It is possible that calling a conversion exit with "bad" data can cause the connection to R/3 to be terminated.

     I encountered this issue when developing a component that encapsulates (amongst other areas) access to the conversion BAPIs. To be able to test my component with different SAP releases without having to write specific test code, I made the component self-testing, i.e., I wrote a method that tries out every conversion exit referenced by any BAPI parameter in a particular release. Then, to make sure that the component would work properly if the client program tried to convert inappropriate data (e.g., a unit of measurement not defined in SAP), I called each conversion exit with data that should never work.

      Running this self-test method for the first time, I got more error messages than I had expected. Only the first few exits seemed to be called correctly, everything after that failed. When I investigated the reason for this behavior, I found that some conversion exits, when passed data they did not like, tried to write an "A" (as in "Abort") message to SAPGUI. This is, of course, inappropriate behavior inside a BAPI, since a BAPI-enabled application usually does not have SAPGUI enabled. The RFC layer reacts by terminating the session with R/3, which explains why further calls after the first failed conversion did not work.

     The conversion exits should not be blamed for this. After all, they were written to be part of SAPGUI and expect to be called only with valid data, since SAPGUI calls the validation first and only invokes the exit when the entered data has passed the validation. What should happen is that the conversion BAPIs try to catch the error messages by the conversion exits and convert them into normal return codes.

SAP to the Rescue

I informed SAP about the problem and sent them the list of all "dangerous" conversion exits used in BAPI parameters in the various releases (see Figure 1). SAP reacted quickly by improving the conversion BAPIs (see OSS Note 215418). If you are using the conversion BAPIs in your own applications, it is highly recommended that you update the conversion BAPIs by applying the support packages listed in the OSS Note (applicable to releases 4.0B through 4.6C). Otherwise, you may experience intermittent application problems that could be hard to fix, unless you already have heard about the issue and the user remembers exactly what data was entered into the application.

Conversion Exit Name
Used Since Release

AOBAR
CUNIT
GJAHR
KONPR
PDATE
SCOPE

4.0

CFOBR
EXCRT
OBART
PARC1
PERKZ
SPDEV
TPLNR

4.5
ABPSP
TSTPS
4.6
Figure 1 "Dangerous" Conversion Exits Used in BAPI Parameters

Dim oSession As RfcSession

Private Sub Command1_Click()
Dim oBapiService As BapiService
Dim rsData As Recordset
Dim rsReturn As Recordset
  Set oBapiService = _
    oSession.CreateInstance("ARAsoft.BapiService")
  Call oBapiService.DimAs("BapiDataConversionExt2Int", _
		"Data", rsData)
  rsData.AddNew
  rsData("OBJNAME") = "AcctngActivityAlloc"
  rsData("METHOD") = "Check"
  rsData("PARAMETER") = "DocItems"
  rsData("FIELD") = "ACTIVITYUN"
  rsData("EXT_FORMAT") = Text1.Text
  rsData.Update
  On Error Resume Next
  oBapiService.BapiDataConversionExt2Int Data:=rsData, _
		Return:=rsReturn
  If Err.Number = 0 Then
    If rsReturn Is Nothing Then
      MsgBox rsData("INT_FORMAT"), , App.Title
    End If
  Else
    MsgBox Err.Description
  End If
End Sub

Private Sub Form_Load()
Dim sLogonErrMessage As String
  If Not Logon(oSession, sLogonErrMessage) Then
    MsgBox sLogonErrMessage, , App.Title
  End If
End Sub

Private Function Logon(Session As RfcSession, _
                     Optional ErrMessage As String) As Boolean
Dim ldSuccess As ARAsoftDLC.LOGONDIALOGRESULT
  Set Session = New RfcSession
  ldSuccess = ARAsoftDLC.LogonDialog(Session, ErrMessage)
  If ldSuccess = Success Then
    Logon = True
  ElseIf ldSuccess = Failure Then
    Logon = False
  ElseIf ldSuccess = Cancel Then
    Logon = False
  End If
End Function

Listing 1 Conversion Test Program

     To allow you to reproduce the behavior discussed above, and also as an introduction to using the conversion BAPIs if this is the first time you have encountered them, I have written the sample program shown in Listing 1 above.

     Figure 2 shows the sample program in action. We are about to convert the unit PC to its internal representation.

Figure 2 Converting a Unit of Measurement

      In Figure 3, we get the expected message box, with the converted value ST.

Figure 3 The Converted Unit (Internal Format)

     Now we will try the non-existing unit "1A" (see Figure 4).

Figure 4 Trying to Convert a "Bad" Unit

     The result is the error message in Figure 5. What this error message does not tell us is that our connection to R/3 was terminated.

Figure 5 The Error Message Issued by the Conversion Exit

      If we were to try again to convert a valid value (or indeed if we were to call any BAPI or RFM) now, we would get the error depicted in Figure 6.

Figure 6 No More Connection to SAP

      Of course, we could write extra application code trying to cope with the issue described here, but it is much simpler to use the improved version of the conversion BAPIs!

     While the sample code in Listing 1 allows you to get started with your own conversion calls, I want to give you some additional hints as to how you might want to address the conversion theme in your own applications:

  • Oftentimes, an entity using conversion exits also supports the Helpvalues.GetList BAPI. If you have encapsulated all your calls to Helpvalues.GetList³ into one component (highly recommended), you should deal with the conversions required for the supported entities in the same component. If you have two classes, Languages and Language, for example, to deal with language codes,4 then you could add an additional property, InternalCode, to your Language class. When the client program accesses this property for the first time, you would call the BapiService.DataConversionExt2Int1 BAPI for all languages in your Languages object (which you filled earlier by a call to Helpvalues.GetList) and store the results (the converted values) in the InternalCode property of all the Language objects. (Remember that Helpvalues.GetList will always return the external format of any entity.)

  • As indicated in the previous hint, it is a good idea to bundle your conversions. Calling SAP once with several values to convert is much better for performance than making individual calls for each value.

  • When converting more than one value, though, be aware that the conversion BAPIs sort the table in which the data is contained (parameter Data) in order to improve the BAPI's performance. This requires us to be careful when extracting the converted values. Setting the ROWNUMBER field of each row in the Data table to a unique value enables you to re-establish the proper sequence.

  • For the ALPHA conversion exit used to add or remove leading zeroes (which is done for customer numbers and similar entities), you should provide a local implementation on the client side. Writing the required code is really trivial, and there is no good justification for wasting precious SAP resources in this case.

¹ Most Data Dictionary fields are based on Data Elements, which, in turn, are based on Domains.

² For details about how to use these BAPIs, please refer to the SAP documentation (and the sample program discussed later).

³ The structure of the data returned by this BAPI can change between SAP releases. In order to limit the number of components and applications that you have to test whenever you upgrade your SAP system, you should put all your calls to this BAPI into one component.

4 SAP (since 4.0) uses the 2-byte ISO language codes in SAPGUI, but internal format (used in most BAPI's) is still the old 1-byte SAP language code.


Thomas G. Schuessler is the founder of ARAsoft (www.arasoft.de), a company offering products, consulting, custom development, and training to a worldwide base of customers. The company specializes in integration between SAP and non-SAP components and applications. ARAsoft offers various products for BAPI-enabled programs on the Windows and Java platforms. These products facilitate the development of desktop and Internet applications that communicate with R/3. Thomas is the author of SAP's CA925 "Programming with BAPIs in Visual Basic" class, which he teaches in Germany and in English-speaking countries. His book on BAPI programming (The BAPI Bible for SAP Programmers: The comprehensive guide to integrating SAP products with Web, desktop, and mobile applications using Java, Visual Basic, and ABAP) will be published soon by the SAP Professional Journal. For more information, see www.SAPpro.com/BAPIBible. Thomas is a regularly featured speaker at SAP TechEd and SAPPHIRE conferences. Prior to founding ARAsoft in 1993, he worked with SAP AG and SAP America for seven years. Thomas can be contacted at thomas.schuessler@sap.com or at tgs@arasoft.de.

An email has been sent to:






More from SAPinsider



COMMENTS

Please log in to post a comment.

No comments have been submitted on this article. Be the first to comment!


SAPinsider
FAQ