GRC
HR
SCM
CRM
BI


Article

 

BAPI Bulletin: Java BAPI Programming Helper Methods

by Thomas G. Schuessler | SAPinsider

October 1, 2000

by Thomas G. Schuessler, SAP AG SAPinsider - 2000 (Volume 1), October (Issue 2)
 

Based on the feedback I get, a lot more companies seem to be writing serious BAPI-enabled applications (mostly server-based) in Java these days. For that reason, I want to share with you some Java helper methods I wrote recently to facilitate certain aspects of BAPI programming.

A Little Bit of ABAP

Let us start with an idea I stole from ABAP. Java programmers may be surprised that a procedural language¹ can offer ideas worth stealing in the first place, but some features of ABAP are cool even viewed with a Java background. For example, ABAP contains a statement called MOVE-CORRESPONDING <structureA > TO <structureB>. This statement takes the contents of all fields in structure A that also exist in structure B and copies them into the appropriate fields of structure B. ABAP bases its decision about which fields to include in the copy process only on the names of the fields in the two structures.

     Since we are dealing with structures a lot in BAPI-enabled applications (as structure parameters and rows of table parameters), such a feature can be very useful in Java, too. My implementation, shown in Listing 1, can be used to copy fields from one structure or table row to another. This can be accomplished easily since both IRow and IStructure extend IComplexField.


public final static int moveCorresponding
  (IComplexField from, IComplexField to) {
SimpleInfo si;
SimpleInfo sj;
int count = 0;
  int fci = from.getFieldCount();
  int fcj = to.getFieldCount();
  for (int i = 0; i < fci; i++) {
    si = from.getSimpleField(i).getSimpleInfo();
    for (int j = 0; j < fcj; j++) {
      sj = to.getSimpleField(j).getSimpleInfo();
      if (si.equals(sj)) {
        to.getSimpleField(j).setTypedValue
          (sj.getType(),
from.getSimpleField(i).getTypedValue(sj.getType()));
        count++;
        break;
      }
    }
  }
  return count;
}
Listing 1 The moveCorresponding Method

     In contrast to ABAP, my version not only compares field names, but also all relevant metadata (available in SimpleInfo) before allowing the copy to proceed for a field. As an added benefit, moveCorresponding returns the number of fields that it copied - which could be used, for example, to verify that all fields of a structure were successfully copied to a table row.

Parameter Defaults

BAPIs can have import parameters that are simple fields (a.k.a. scalar parameters). These can be defined as optional or mandatory. The ABAP developer of the BAPI can also define a default value for each scalar import parameter.

     Obviously, it would be nice to know what the default is for any given parameter, e.g., to show it to the user in the appropriate data entry field. Retrieving the proper default information can be a little tricky, since ABAP allows the developer not only to use constant strings, but also system variables like SY-LANGU (the logon language selected by the user) or SY-DATUM (the current date). These need to be replaced by the pertinent information at runtime.

     This is why Listing 2 contains a few more lines of code than you may have expected. The method getDefaultForScalarImportParameter requires you to pass the name of the ABAP function module (implementing a BAPI) and the parameter name. If I want to know the default for the Textformat parameter of the BapiService.ApplicationLogGetDetail BAPI, for example, I have to pass "BAPI_APPLICATIONLOG_GETDETAIL" as the first parameter and "TEXTFORMAT" as the second parameter. The result will be the string "ASC".


public final String getDefaultForScalarImportParameter
  (String pRfmName, String pParameterName) {
  try {
    if (rfmRFC_GET_FUNCTION_INTERFACE == null) {
      rfmRFC_GET_FUNCTION_INTERFACE = 
        FactoryManager.getSingleInstance().getRfcModuleFactory().
          autoCreateRfcModule(mConnection,
            "RFC_GET_FUNCTION_INTERFACE");
    }
    rfmRFC_GET_FUNCTION_INTERFACE.setConnection(mConnection);
    rfmRFC_GET_FUNCTION_INTERFACE.getSimpleImportParam("FUNCNAME").
      setString(pRfmName);
    rfmRFC_GET_FUNCTION_INTERFACE.callReceive();
    ITable params =
      rfmRFC_GET_FUNCTION_INTERFACE.getTableParam("PARAMS");
    IRow row;
    String sDefault; 
    for (int i = 0; i < params.getRowCount(); i++) {
      row = params.getRow(i);
      if (row.getSimpleField("PARAMCLASS").getString().equals("I") &&
        	row.getSimpleField("PARAMETER").getString().
          equals(pParameterName)) {
        sDefault = row.getSimpleField("DEFAULT").getString();
        if (sDefault.equals("SPACE") || sDefault.equals("'"))
          return "";
        if (sDefault.equals("SY-LANGU"))
          return getUserLogonLanguage();
        if (sDefault.equals("SY-DATUM")) {
          java.util.Date date = new java.util.Date();
          java.text.SimpleDateFormat formatter
            = new java.text.SimpleDateFormat ("yyyyMMdd");
          return formatter.format(date);
        }
        if (sDefault.startsWith("'") && sDefault.endsWith("'")) 
          return sDefault.substring(1, sDefault.length() - 1);
        if (sDefault.equals("")) return null;
          return sDefault;
      }
    }
  }
  catch (Exception ex) {}
  return null; 
}
Listing 2 The getDefaultForScalarImportParameter Method

     If you study the source code, you will notice a few things:

  • If there is no default (or we run into a problem while we try to retrieve it), the method returns null. This allows the client program to differentiate between no default and a default defined as an empty string.

  • RFC-enabled Function Module RFC_GET_FUNCTION_INTERFACE is called without using any generated proxy classes. This causes a slight performance degradation the first time the function is invoked, but allows me to avoid having to distribute several additional classes.

  • The logon language selected (its 1-byte code, to be exact) is retrieved by a call to getUserLogonLanguage. This method is explained in the following section.

  • The current date (for SY-DATUM) is returned in the internal ABAP date format YYYYMMDD. You can easily adjust the code to use whatever date format you prefer.

The Logon Language

Knowing the logon language code is not only important for the getDefaultForScalarImportParameter method, discussed above.

     Calling BapiService.FieldhelpGetDocu, for example, will fail if you do not set the Language parameter. There is no default for it. Strangely, there does not seem to be a way to figure out which language was selected without a call to R/3. The UserInfo class's getLanguage method returns the string the program used when setting the property. This could be a 1-byte language code, a 2-byte (ISO) language code, or nothing at all if the user is willing to use the default language defined by the system administrator for this R/3 system.

     Fortunately, RFC_GET_SAP_SYSTEM_PARAMETERS allows us to retrieve the language code as well as some other useful information. Listing 3 shows you how to call the function module. All the other interesting information is put into member variables (accessible through methods that are too trivial to list here).

     Hopefully some of these helper methods will be useful for your own Java BAPI projects. If there are additional areas that you would like to be encapsulated, let me know, and I will try to cover them in future columns.


public final String getUserLogonLanguage() {
  if (mUserLogonLanguage != null) return mUserLogonLanguage;
  try {
    if (rfmRFC_GET_SAP_SYSTEM_PARAMETERS == null) {
        rfmRFC_GET_SAP_SYSTEM_PARAMETERS =
          FactoryManager.getSingleInstance().getRfcModuleFactory().
            autoCreateRfcModule(mConnection,
              "RFC_GET_SAP_SYSTEM_PARAMETERS");
        rfmRFC_GET_SAP_SYSTEM_PARAMETERS.setConnection(mConnection);
        rfmRFC_GET_SAP_SYSTEM_PARAMETERS.callReceive();
        mUserLogonLanguage = rfmRFC_GET_SAP_SYSTEM_PARAMETERS.
          getSimpleExportParam("LANGUAGE").getString();
        mUserName = rfmRFC_GET_SAP_SYSTEM_PARAMETERS.
          getSimpleExportParam("USER_NAME").getString();
        mSapDateFormat = rfmRFC_GET_SAP_SYSTEM_PARAMETERS.
          getSimpleExportParam("DATE_FORMAT").getString();
        mSapDecimalSymbol = rfmRFC_GET_SAP_SYSTEM_PARAMETERS.
          getSimpleExportParam("DECIMAL_SIGN").getString();
        mSapRelease = rfmRFC_GET_SAP_SYSTEM_PARAMETERS.
          etSimpleExportParam("SAP_SYSTEM_RELEASE").getString();
    }
  }
  catch (Exception ex) { return ""; }
  return mUserLogonLanguage;
}
Listing 3 The getUserLogonLanguage Method

To Learn More...

For those of you who do not use Java for your BAPI projects yet but suspect that you might be missing out on something, consider taking SAP's CA926 "Programming with BAPIs in Java" class, offered in Germany (in German), the UK (good Indian restaurant nearby), and the USA (pick Foster City if you want incredible Chinese food). Make sure to brush up on your Java programming skills first, though, since knowing Java is the (only) prerequisite for attending this class.      Please contact the appropriate SAP country organization for information about scheduled classes and available seats. 1 I know, I know, ABAP is now an object-oriented language, as well. But not many developers seem to take advantage of those new capabilities yet. Listing 1 The moveCorresponding Method Listing 2 The getDefaultForScalarImportParameter Method


¹ I know, I know, ABAP is now an object-oriented language as well. But not many developers seem to take advantage of those new capabilities yet.

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. 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 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