Coding Client Applications and Services
Overview
Adapter for SAP has several APIs that you can use in your client applications and services. This chapter shows how to use the built-in services API to invoke SAP RFCs, send IDocs to an SAP system and to receive an IDoc from an SAP system. For descriptions of the available built-in services, refer to Built-in Services.
For more information about building the Java services, see the online API documentation installed with Integration Server at: Integration Server_directory\instances\instance_name\doc\api\Java\index.html
This chapter also shows how to use IBM webMethods Adapter for SAP IDoc Java API to construct an IDoc. For information, refer to packages_directory\WmSAP\pub\doc\api\index.html.
Invoking RFCs from Adapter for SAP
Calling Public Adapter for SAP Services from Java Services
About this task
This section shows an example of how to invoke an RFC from a Java service. The sample app/BAPI.javathat is shown below logs on to an SAP system and invokes a BAPI.
For more information about developing services, see IBM webMethods Service Development Help for your release and the online API documentation.
To call a public Adapter for SAP service from Java
Procedure
Receiving IDocs from an SAP System
To receive an IDoc from an SAP system and pass it to a service, you can setup an synchronous ALE adapter notification or a routing notification. In either case, you need to assign the service you would like to invoke to the notification. For instructions on establishing routing notifications, refer to Routing Notifications. When choosing the transport for the routing notification, select the IS transport. For instructions on establishing asynchronous ALE listener notifications, refer to Creating a Synchronous RFC Adapter Notification.
Accessing and Modifying Fields in IDocs
The following code sample shows how to use the SAP Java IDoc Class Library to convert an IDoc to a structured document with direct access to each field. This allows you to modify an IDoc's contents on the fly. For example, if you want to customize incoming IDocs based on local data format, you can do so.
IDataCursor idc=pipeline.getCursor();
com.sap.conn.idoc.IDocDocumentList iDocList=null;
if (idc.first("iDocList"))
iDocList=(com.sap.conn.idoc.IDocDocumentList) idc.getValue();
under Shared > Imports, include the lines:
com.wm.adapter.sap.idoc.*
com.sap.conn.idoc.*
For more information about using the SAP Java IDoc Class Library, refer to Constructing an IDoc with the SAP Java IDoc Class Library.
Converting an IDoc to XML
The following code sample shows how to convert an IDoc to XML.
String xmlData = idocList.toXML();
Constructing an IDoc with the SAP Java IDoc Class Library
The following sample shows how to construct a new MATMAS IDoc.
com.wm.adapter.sap.idoc.*and
com.sap.conn.idoc.*
in
Shared >
Imports.
public final static void createIDoc (IData pipeline)
throws ServiceException
{
//create a new and empty MATMAS02 document
try
{
com.sap.conn.idoc.IDocDocumentList iDocList = new IDataDocumentList("MATMAS02");
IDocDocument doc = iDocList.addNew();
//set the appropriate control header data
doc.setIDocNumber("0000047112211178");
doc.setClient("000");
doc.setDirection("1");
doc.setRecipientPartnerType("LS");
doc.setMessageType("MATMAS");
doc.setRecipientPartnerType("LS");
doc.setRecipientPartnerNumber("TSTCLNT000");
doc.setSenderPort("SAPBCIDOC");
doc.setSenderPartnerType("LS");
doc.setSenderPartnerNumber("SBCCLNT000");
doc.setCreationDate("20030511");
doc.setCreationTime("103051");
doc.setSerialization("20030511103051");
//get the root segment from the document
//The root segment does not contain any fields or data. It is only
//used as the standard parent segment and won't be transmitted when
//the document is sent to an SAP system.
IDoc.Segment segment = doc.getRootSegment();
//create and add a new and empty child segment of type E1MARAM
//and fill the segment data
segment = segment.addChild("E1MARAM");
segment.setValue("MSGFN", "005");
segment.setValue("MATNR", "BOXCOOKIES");
segment.setValue("ERSDA", "20030303");
segment.setValue("ERNAM", "TOPSI");
segment.setValue("PSTAT", "KBG");
segment.setValue("MTART", "FERT");
segment.setValue("MBRSH", "L");
segment.setValue("MATKL", "G1113");
segment.setValue("MEINS", "PCE");
segment.setValue("BLANZ", "000");
segment.setValue("BRGEW", "0.550");
segment.setValue("NTGEW", "0.000");
segment.setValue("GEWEI", "KGM");
segment.setValue("VPSTA", "KBG");
//create and add a new and empty child segment of type E1MAKTM
//and fill the segment data
segment = segment.addChild("E1MAKTM");
segment.setValue("MSGFN", "005");
segment.setValue("SPRAS", "D");
segment.setValue("MAKTX", "Schachtel mit Keksen");
segment.setValue("SPRAS_ISO", "DE");
//create and add a new and empty sibling segment of type E1MAKTM (same
//type) and fill the segment data
segment = segment.addSibling();
segment.setValue("MSGFN", "005");
segment.setValue("SPRAS", "E");
segment.setValue("MAKTX", "Box of cookies");
segment.setValue("SPRAS_ISO", "EN");
//create and add a new and empty sibling segment of type E1MARCM
//and fill the segment data
segment = segment.addSibling("E1MARCM");
segment.setValue("MSGFN", "005");
segment.setValue("WERKS", "0001");
segment.setValue("PSTAT", "BG");
segment.setValue("PLIFZ", "0");
segment.setValue("WEBAZ", "0");
segment.setValue("PERKZ", "M");
segment.setValue("AUSSS", "0.00");
segment.setValue("BESKZ", "E");
segment.setValue("AUTRU", "X");
//create and add a new and empty sibling segment of type E1MBEWM
//and fill the segment data
segment = segment.addSibling("E1MBEWM");
segment.setValue("MSGFN", "005");
segment.setValue("BWKEY", "0001");
segment.setValue("VPRSV", "S");
segment.setValue("VERPR", "0.00");
segment.setValue("STPRS", "15.50");
segment.setValue("PEINH", "1");
segment.setValue("BKLAS", "7920");
segment.setValue("VJVPR", "S");
segment.setValue("VJVER", "0.00");
segment.setValue("VJSTP", "15.50");
segment.setValue("LFGJA", "2002");
segment.setValue("LFMON", "08");
segment.setValue("PSTAT", "BG");
segment.setValue("KALN1", "000100126602");
segment.setValue("KALNR", "000100126603");
segment.setValue("EKALR", "X");
segment.setValue("VPLPR", "0.00");
segment.setValue("VJBKL", "7920");
segment.setValue("VJPEI", "1");
segment.setValue("BWPEI", "0");
IDataCursor idc=pipeline.getCursor();
IDataUtil.put(idc, "iDocList", iDocList);
idc.destroy();
}
catch (Exception e)
{
throw new ServiceException(e);
}
Sending IDocs to an SAP System
About this task
The basic steps to send an outbound IDoc from either a client or a service are:
Procedure
Transaction Features for HTTP and SAP-XML
When executing HTTP Posts using IDoc-XML and XRFC with transactions, you should make sure that your client correctly handles such calls. It should have transaction management that supports at least the following features:
- Transaction ID generation.
- Resending documents with same transaction ID in error cases.
- After a successful execution of a transaction, a document cannot be sent again.
To transfer the transaction ID to Adapter for SAP, you add an extra header to the HTTP POST, x-tid, that contains the transaction ID.
Example: HTTP POST of an IDoc
POST /invoke/pub.sap.transport.ALE/InboundProcess HTTP/1.0
X-tid: 9B38FA81133A38B518A10036
Content-type: application/x-sap.idoc
Content-Length: 4242
<?xml version="1.0" encoding="iso-8859-1"?>
<MATMAS02>
<IDOC BEGIN="1">
<EDI_DC SEGMENT="1">
<TABNAM>EDI_DC</TABNAM>
<MANDT>000</MANDT>
<DOCNUM>0000047112211178</DOCNUM>
<DOCREL/>
<STATUS/>
<DOCTYP>MATMAS02</DOCTYP>
<DIRECT>1</DIRECT>
...
For XRFC documents, you can also put the transaction ID in the header of the document:
<?xml version="1.0"?>
<sap:Envelope xmlns:sap="urn:sap-com:document:sap" version="1.0">
<sap:Header xmlns:rfcprop="urn:sap-com:document:sap:rfc:properties">
<rfcprop:Transaction>0A1104DC080C3C60F9E106A1</rfcprop:Transaction>
</sap:Header>
<sap:Body>
<rfc:SBC_TEST_SAVE xmlns:rfc="urn:sap-
com:document:sap:rfc:functions">
<INPUT>Have fun!</INPUT>
</rfc:SBC_TEST_SAVE>
</sap:Body>
</sap:Envelope>
Calling a BAPI Synchronously from SAP System
About this task
This example demonstrates how to send the BAPI CompanyCode.GetDetail from an SAP system to the Web via XML.
As the BAPI will be handled by a routing notification, you need to specify some information to enable correct routing. For this purpose, you should use the parameter SBCHEADER when calling the RFC function module from the SAP system.
To set up for the example
Procedure
Preparing a Routing Notification for the BAPI Call
About this task
Before executing the report in the section Calling a BAPI Synchronously from SAP System, you should specify a routing notification to the XML transport. You can send the XML message to any server that is able to process the HTTP Post message and send back a correct response. In this example, the call will be sent back to the locally installed Integration Server to demonstrate its inbound XML processing capabilities.
To prepare a routing notification for the BAPI call
Procedure
Specifying a Second Routing Notification for the BAPI
About this task
To handle the inbound XML message, which will now be sent back to the local Integration Server, you have to specify a second routing notification for the BAPI:
To specify a second routing notification for the BAPI
Procedure
Results
When using the Integration Server as the remote partner as described above, the BAPI will be executed in the selected system, the exporting and changing parameters will be put in an XML response document and sent back to the calling SAP system.
The report will then display the parameters received from the remote system, which in this case is a list of company codes.
Calling a BAPI Asynchronously from an SAP System
This example demonstrates how to call a BAPI asynchronously from an SAP system over the Web. For this purpose, you have to create an ABAP program inside the SAP system. This program calls the proxy function module to generate an ALE message for a BAPI. After performing a COMMIT WORKcommand, the SAP system will generate an IDoc through the ALE service layer and send it to Adapter for SAP. There the IDoc will be transformed into the original BAPI representation and sent as XML using HTTP to any remote web system.
BAPI_, the
corresponding ALE proxies are usually named equally with the prefix
ALE_
To run an example, you should set up your SAP system for ALE processing as described in the SAP system documentation and in this guide. When defining the partner profile for the outgoing IDoc in the SAP system, ensure that the option Transfer IDoc immediatelyis selected because the BAPI conversion tool on Adapter for SAP does not support IDoc packages.
Create the following report in your SAP system to test the BAPI conversion with the BAPI Bank.Create(available as of SAP release 4.6C).
REPORT Z_BAPI_ALE_DEMO .
parameters receiver like BDI_LOGSYS-LOGSYS.
parameters country like BAPI1011_KEY-BANK_CTRY default 'DE'.
parameters bankkey like BAPI1011_KEY-BANK_KEY default '34981255'.
data: receivers like BDI_LOGSYS occurs 0 with header line,
address like BAPI1011_ADDRESS.
*prepare the distribution information
move receiver to receivers-LOGSYS.
append receivers.
*prepare the BANK addres parameter
address-BANK_NAME = 'Demo Bank'.
address-REGION = 'BW'.
address-STREET = 'Neurottstr. 16'.
address-CITY = 'Walldorf'.
address-SWIFT_CODE = 'ABCDDE12'.
address-BANK_GROUP = 'SB'.
address-BANK_NO = '12345678'.
address-ADDR_NO = '123'.
*send data to ALE
CALL FUNCTION 'ALE_BANK_CREATE'
EXPORTING
BANKCTRY = country
BANKKEY = bankkey
BANKADDRESS = address
TABLES
RECEIVERS = receivers
EXCEPTIONS
ERROR_CREATING_IDOCS = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
write: / 'IDoc could not be created'.
ELSE.
write: / 'IDoc successfully created'.
ENDIF.
*trigger processing
commit work and wait.
Creating Similar Routing Notifications
About this task
To create similar routing notifications
You can create routing notifications similar to those described in the synchronous example.
Procedure
Handling Inbound XML Message
About this task
To handle the inbound XML message, which will now be sent back to the local Integration Server, you have to specify a second routing notification for the BAPI.
To handle the Inbound XML Message
Procedure
Example of an XML
When executing the report in the SAP system, Adapter for SAP will transmit the XML document via HTTP (names of logical systems depend on your system configuration). The XML would look like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<biztalk_1 xmlns="urn:biztalk-org:biztalk:biztalk_1">
<header>
<delivery>
<message>
<messageID>0A125F1315B3A11B00000035</messageID>
<sent>2000-06-07T09:22:40</sent>
</message>
<to>
<address>urn:sap-com:logical-system:CERCLNT750</address>
</to>
<from>
<address>urn:sap-com:logical-system:CERCLNT800</address>
</from>
</delivery>
</header>
<body xmlns="">
<doc:Bank.Create xmlns:doc="urn:sap-com:document:sap:business">
<BankKey>34981243</BankKey>
<BankCtry>DE</BankCtry>
<BankAddress>
<BANK_NAME>Demo Bank</BANK_NAME>
<REGION>BW</REGION>
<STREET>Neurottstr. 16</STREET>
<CITY>Walldorf</CITY>
<SWIFT_CODE>ABCDDE12</SWIFT_CODE>
<BANK_GROUP>SB</BANK_GROUP>
<POBK_CURAC></POBK_CURAC>
<BANK_NO>12345678</BANK_NO>
<POST_BANK></POST_BANK>
<BANK_BRANCH></BANK_BRANCH>
<ADDR_NO>123</ADDR_NO>
</BankAddress>
</doc:Bank.Create>
</body>
</biztalk_1>
You can check the correct processing of your BAPI-call in the IDoc status monitor.

In the target SAP system, you can also inspect the correct processing using the ALE status monitor (BD87 in SAP release 4.6C. IDoc lists can also be displayed with WE05). If any application errors occurred, they are listed in the IDoc monitor.