Using custom business object handlers

It is recommended that you use the BAPI business object handler delivered with the connector as a template (for details, see Business object processing), rather than write your own business object handler. Reasons for using custom business object handlers include the following:

Creating custom business object handlers

If you decide to create a custom business object handler, consider the following example as a guide for how to code it. Note that SAPODA does not generate the code for you.

package bapi.client ;
 
 
import AppSide_Connector.JavaConnectorUtil;
import CxCommon.BusinessObjectInterface;
import CxCommon.CxMsgFormat;
import CxCommon.CxStatusConstants;
import CxCommon.ReturnStatusDescriptor;
import com.crossworlds.connectors.sap.codegen.BapiBOHandlerBase;
import com.crossworlds.connectors.sap.codegen.exception.CwBoHandlerAppResponseTimeout;
import com.crossworlds.connectors.sap.codegen.exception.CwBoHandlerProcessingFailed;
import com.crossworlds.connectors.sap.visionframework.VisionBOHandlerInterface;
import com.crossworlds.connectors.sap.visionframework.VisionConnectorAgent;
import com.sap.mw.jco.IRepository;
import com.sap.mw.jco.JCO;
 
 
public class Bapi_customer_getlist extends BapiBOHandlerBase implements VisionBOHandlerInterface {
 
  private static VisionConnectorAgent vca = VisionConnectorAgent.getCWSapConnManager();
  private IRepository repository = getRepository();
  private JCO.Function bapicommit = new JCO.Function(repository.
     getFunctionTemplate("BAPI_TRANSACTION_COMMIT"));
  private int checkBapiReturn = CxStatusConstants.SUCCEED;
 
  public Bapi_customer_getlist()
  {
  }
 
 
  public int doVerbForVision(BusinessObjectInterface theObj, ReturnStatusDescriptor rtn)
  {
     JCO.Function function = new JCO.Function(repository.getFunctionTemplate("BAPI_CUSTOMER_GETLIST"));
 
     //Default processing to failure
     int    mReturnCode = CxStatusConstants.FAIL;
     JCO.Client theClient = null;
 
     try
     {
     traceMessage(JavaConnectorUtil.LEVEL1, 27025, CxMsgFormat.XRD_INFO, theObj.getName(), theObj.getVerb(),
 null, null);
 
     // get defaults and check for required fields for Create and Update only
     if ((theObj.getVerb().equalsIgnoreCase("Create")) || (theObj.getVerb().equalsIgnoreCase("Update")))
     {
       traceMessage(JavaConnectorUtil.LEVEL4, 27021, CxMsgFormat.XRD_INFO, theObj.getName(),
   null, null, null);
       JavaConnectorUtil.initAndValidateAttributes(theObj);
     }
 
     // get a new connection to Sap
     theClient = this.getClient();
 
     //   populate Rfc interface parameters
     mReturnCode = doBusObjtoRfcData(theObj, function, function.getImportParameterList(),"I",false);
     if (mReturnCode != CxStatusConstants.SUCCEED)
     {
       if (theClient != null) vca.releaseClient(theClient);
       return CxStatusConstants.FAIL;
     }
 
     // Execute Rfc Call
     this.callBapi(theClient,function);
 
     try {
     // After successful RfcCall: check Structure/Table RETURN for Bapi Return Codes E or A that
     // indicate failure
       this.checkBapiRc(function);
 
     // After successful Bapi Call: call BAPI_TRANSACTIOM_COMMIT
       this.callBapiCommit(theClient);
 
     } catch (CwBoHandlerProcessingFailed cwpf) {
       rtn.setErrorString(cwpf.getMessage());
       rtn.setStatus(CxStatusConstants.FAIL);
       checkBapiReturn = CxStatusConstants.FAIL;
     }
     // Now create CW Business Object
     mReturnCode = doRfcDatatoBusObj(theObj, function , function.getExportParameterList(), "E");
     if (mReturnCode != CxStatusConstants.SUCCEED || checkBapiReturn != CxStatusConstants.SUCCEED)
     {
       if (theClient != null) vca.releaseClient(theClient);
       return CxStatusConstants.FAIL;
     }
 
     // Clean up
     if (theClient != null) vca.releaseClient(theClient);
 
     // Finally, return success to ICS
     traceMessage(JavaConnectorUtil.LEVEL1, 27034, CxMsgFormat.XRD_INFO, theObj.getName(),
        null, null, null);
     return CxStatusConstants.VALCHANGE;
     }//end of try
 
     catch (CxCommon.Exceptions.SetDefaultFailedException sdfe)
     {
       if (theClient != null) vca.releaseClient(theClient);
       String msg = logMessage(20059, CxMsgFormat.XRD_INFO, theObj.getName(), null, null, null);
       rtn.setErrorString(msg);
       rtn.setStatus(CxStatusConstants.FAIL);
       return CxStatusConstants.FAIL;
     }
     catch (CxCommon.Exceptions.BusObjSpecNameNotFoundException c)
     {
       if (theClient != null) vca.releaseClient(theClient);
       String msg = logMessage(20059, CxMsgFormat.XRD_INFO, theObj.getName(), null, null, null);
       rtn.setErrorString(msg);
       rtn.setStatus(CxStatusConstants.FAIL);
       return CxStatusConstants.FAIL;
     }
     catch (CwBoHandlerAppResponseTimeout art)
     {
       if (theClient != null) vca.releaseClient(theClient);
       rtn.setErrorString(art.getMessage());
       rtn.setStatus(CxStatusConstants.APPRESPONSETIMEOUT);
       return CxStatusConstants.APPRESPONSETIMEOUT;
     }
     catch (CwBoHandlerProcessingFailed cwpf)
     {
       if (theClient != null) vca.releaseClient(theClient);
        rtn.setErrorString(cwpf.getMessage());
       rtn.setStatus(CxStatusConstants.FAIL);
       return CxStatusConstants.FAIL;
     }
     catch (Exception e)
     {
       if (theClient != null) vca.releaseClient(theClient);
        rtn.setErrorString(e.getMessage());
       rtn.setStatus(CxStatusConstants.FAIL);
       return CxStatusConstants.FAIL;
     }
     catch ( OutOfMemoryError merr ){                // CR 30185
       String msg = logMessage(23060, JavaConnectorUtil.XRD_ERROR, 
         "doVerbForVision()", merr.toString(), null, null);
       rtn.setErrorString(msg);
       rtn.setStatus(CxStatusConstants.APPRESPONSETIMEOUT);
       return CxStatusConstants.APPRESPONSETIMEOUT;
     }
     catch ( StackOverflowError serr ){                // CR 30185
       String msg = logMessage(23060, JavaConnectorUtil.XRD_ERROR,
          "doVerbForVision()", serr.toString(), null, null);
       rtn.setErrorString(msg);
       rtn.setStatus(CxStatusConstants.APPRESPONSETIMEOUT);
       return CxStatusConstants.APPRESPONSETIMEOUT;
     }
     catch (Throwable ex) {
       // 23046 EXception raised in: {1} : ErrorMessage: {2}.
       String msg = logMessage(23046, JavaConnectorUtil.XRD_ERROR, 
         "doVerbForVision()",ex.toString(), null, null);
       return CxStatusConstants.FAIL;
     }
  }// end of doVerbforVision
 
public int callBapiCommit(JCO.Client theClient) throws 
    CwBoHandlerProcessingFailed, CwBoHandlerAppResponseTimeout
{
 
  int mStatus = CxStatusConstants.FAIL;
  try {
  traceMessage(JavaConnectorUtil.LEVEL3, 27032, CxMsgFormat.XRD_INFO, null, null, null, null);
  try
  {
     theClient.execute(bapicommit);
  }
  catch (JCO.Exception e)
  {
     String msg = logMessage(27019, CxMsgFormat.XRD_ERROR, null, null, 
      null, null);
     throw new CwBoHandlerProcessingFailed(msg);
  }
  //  Read Return
  readBapiRc(bapicommit.getExportParameterList().getStructure("RETURN"));
  }// end of try
  catch (Exception e)
  {
     String msg = logMessage(27019, CxMsgFormat.XRD_ERROR, null, null,
       null, null);
     throw new CwBoHandlerProcessingFailed(e.getMessage());
  }
 
  // Return Success
  return CxStatusConstants.SUCCEED;
}
 
 
public void checkBapiRc(JCO.Function function) throws CwBoHandlerProcessingFailed
{
 
  try
  {
     JCO.ParameterList p = function.getTableParameterList();
       this.readBapiRc(p.getTable("RETURN"));
     }
     catch (CwBoHandlerProcessingFailed cw)
     {
       throw cw;
     }
     catch (Exception e)
     {
       try
       {
       JCO.ParameterList p = function.getExportParameterList();
       if (p != null)
       this.readBapiRc(p.getStructure("RETURN"));
       else
       {
       String msg = logMessage(27045, CxMsgFormat.XRD_INFO, null,null, null, null);
       throw new CwBoHandlerProcessingFailed(msg);
       }
       }//end try
       catch (JCO.Exception o)
       {
       String msg = logMessage(27045, CxMsgFormat.XRD_INFO, null,null, null, null);
       throw new CwBoHandlerProcessingFailed(msg);
       }
  }
 
}// end of checkBapiRc
 
 
public void readBapiRc(JCO.Structure Return) throws CwBoHandlerProcessingFailed
{
  String type = null;
  String no = null;
  String message = null;
  traceMessage(JavaConnectorUtil.LEVEL4, 27033, CxMsgFormat.XRD_INFO, null, null, null, null);
  if (Return.getString("TYPE") != null)
  {
     // Depending on RETURN ddic structure, number field is either "NUMBER" or "CODE".
     try
     {
       no = Return.getString("NUMBER");
     }
     catch (JCO.Exception o)
     {
       no = Return.getString("CODE");
     }
     message = Return.getString("MESSAGE");
     type = Return.getString("TYPE");
     if ((type.equalsIgnoreCase("A")) || (type.equalsIgnoreCase("E")))
     {
       String msg = logMessage(27015, CxMsgFormat.XRD_ERROR, type, no,
         message, null);
       throw new CwBoHandlerProcessingFailed(msg);
     }
     else
     {
     traceMessage(JavaConnectorUtil.LEVEL1, 27016, CxMsgFormat.XRD_INFO,
       type, no, message, null);
     return;
     }
  }
  // If structure Return is empty, it will be assumed that processing was
     successful
  traceMessage(JavaConnectorUtil.LEVEL1, 27036, CxMsgFormat.XRD_INFO, type, no, message, null);
}
 
 
 
 
public void readBapiRc(JCO.Table Return) throws CwBoHandlerProcessingFailed
{
  String type = null;
  String no = null;
  String message = null;
  String msg = null;
  String errorMsg = "";
  int mStatus = CxStatusConstants.SUCCEED;
 
  traceMessage(JavaConnectorUtil.LEVEL4, 27033, CxMsgFormat.XRD_INFO, null, null, null, null);
  for (int i=0; i<Return.getNumRows(); i++)
  {
  try
  {
  Return.setRow(i);
  if (Return.getString("TYPE") != null)
  {
     type = Return.getString("TYPE");
     // Depending on RETURN ddic structure, number field is either "NUMBER" or "CODE".
     try
     {
       no = Return.getString("NUMBER");
     }
     catch (JCO.Exception e)
     {
       no = Return.getString("CODE");
     }
     message = Return.getString("MESSAGE");
     }//end if
     }//end try
     catch (Exception o)
     {
  // Could not interprete Return structure ==> Failing event
       msg = logMessage(27043, CxMsgFormat.XRD_ERROR, type, no,
        message, null);
       throw new CwBoHandlerProcessingFailed(msg);
     }
     if  (type != null)
     {
     if ((type.equalsIgnoreCase("A")) || (type.equalsIgnoreCase("E")))
     {
       msg = logMessage(27015, CxMsgFormat.XRD_ERROR, type, no,
        message, null);
       mStatus = CxStatusConstants.FAIL;
     }//end if 
     else
     {
     traceMessage(JavaConnectorUtil.LEVEL1, 27044, CxMsgFormat.XRD_INFO,
          type, no, message, null);
     }
     }//end if type != null
  }//end of for
  if (mStatus == CxStatusConstants.FAIL)
     {
       logMessage(27046, CxMsgFormat.XRD_ERROR, msg, null, null, null);
       throw new CwBoHandlerProcessingFailed(msg);
     }
  // If Return is empty, it will be assumed that processing was successful
  if (Return.getNumRows() <= 0) 
     traceMessage(JavaConnectorUtil.LEVEL1, 27036, CxMsgFormat.XRD_INFO, type, no, message, null);
  else
  traceMessage(JavaConnectorUtil.LEVEL1, 27011, CxMsgFormat.XRD_INFO, null, null, null, null);
}//end of ReadBapiRc
 
 
};

The following example illustrates a script for compiling the custom BOHandler on the Windows platform. Note that to run this script, the JDK must be installed on your machine.

REM @echo off REM 
 
REM init environment
call "%CROSSWORLDS%"\bin\CWODAEnv.bat 
setlocal 
 
REM set classpaths
set WBIA=%CROSSWORLDS%"\lib\WBIA\4.2.0\WBIA.jar
set CWLIB=%CROSSWORLDS%"\lib\CrossWorlds.jar
set AGENT="%CROSSWORLDS%"\ODA\SAP\SAPODA.jar
set JCO_JAR="%CROSSWORLDS%"\ODA\SAP\sapjco.jar
 
set JCLASSES=%AGENT%;%JCO_JAR%;%CWLIB%;%WBIA% 
echo classpath = %JCLASSES% 
 
REM compile the BAPI BOHandler passed as argument
javac -verbose -classpath %JCLASSES% %1 
 
endlocal 
pause

Note:
The connector provides full-backward compatibility for existing installations that use generated (non-custom) business object handlers.

Copyright IBM Corp. 1997, 2004