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