Following are the configurations to be done on the SAP R/3 system to send/Receive IDoc
1) Create One TCP/IP Destination
Use the transaction SM59
Provide a name for the RFC Destination, in our case IDOCTEST
Select connection type as T (TCP/IP connection)
Give a program ID (This is important), here it’s IDOCTEST
Add a description
Now your screen should look as follows
2) Creating port and assigning logical Name
Use the transaction WE21
Right click on Transactional RFC and select New
Give a port name
Select RFC Destination created in step 1
Your screen should look as follows
3) Creating logical system for the IDOC
Use the transaction BD54
Click on new entries
Provide a Name for the logical system
Screen shot should look as follows
4) Creating Partner Agreement
Use the transaction WE20
Select the partner Number
Select partner type as LS
Create outbound partner profile for the ORDERS
Creating inbound parameter for MATMAS as follows
Finally your screen should look as follows
You might be thinking I could not find even a single java code so far, here goes the java part
1) Create a Java project using NWDS
2) Create a folder lib and add the following libraries (sapidoc.jar, sapidocjco.jar, sapjco.jar) all of this are downloadable from http://service.sap.com/connectors
3) Add this jar to the build path
//Code provided along with the IDOC Sample
package com.bcone.test;
import com.sap.mw.idoc.*;
import com.sap.mw.idoc.jco.*;
import com.sap.mw.jco.*;
import java.io.*;
/**
* This sample program demonstrates how to receive IDocs from an SAP system.
* Furthermore it gives a little insight on how to navigate on IDoc segment
* trees demonstrating a sample processing of an ORDERS message.
*
*/
public class IDocReceiver
implements JCO.ServerExceptionListener
{
/** Formatter for timestamp strings. */
private static final java.text.SimpleDateFormat timestampFormat = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
/** Path to write the incoming data. */
private static String incomingPath = "c://";
/** Default constructor. */
public IDocReceiver()
{
}
/**
* Class MyIDocServer is for receiving IDocs and function requests.
* The reason for implementing the class as an inner class of the sample
* program is only to keep all the sample source code within one file.
*/
public static class MyIDocServer
extends JCoIDoc.Server
{
/**
* Overridden constructor of JCoIDoc.Server.
* Choose the constructors that one would like to make public.
*/
public MyIDocServer(String gwhost, String gwserv, String progid,
IRepository jcoRepository, IDoc.Repository idocRepository)
{
super(gwhost, gwserv, progid, jcoRepository, idocRepository);
}//constructor MyIDocServer
/**
* Overridden constructor of JCoIDoc.Server.
* Choose the constructors that one would like to make public.
*/
public MyIDocServer(java.util.Properties properties,
IRepository jcoRepository, IDoc.Repository idocRepository)
{
super(properties, jcoRepository, idocRepository);
}//constructor MyIDocServer
/**
* Overridden method of JCoIDoc.Server.
* Function requests that do not contain IDocs will be handled here.
* These requests will be stored as XML file in the incoming path.
* No other action will be done. The return values won't be filled and
* no exception will be thrown to the caller.
*/
protected void handleRequest(JCO.Function function)
{
System.out.println("Incoming function request '" + function.getName() + "'...");
String filename = function.getName() + "_" +
timestampFormat.format(new java.util.Date()) + ".xml";
System.out.println("Storing function request as XML file '" + filename + "'...");
function.writeXML(incomingPath + filename);
}//method handleRequest
/**
* Overridden method of JCoIDoc.Server.
* Function requests that contain IDocs will be handled here.
* All IDocs will be stored as XML files in the incoming path.
* Additionally, IDocs that are part of an ORDERS message will be
* processed specifically. Some relevant information is extracted from
* these IDocs and will be stored in a text file in the incoming path.
*/
protected void handleRequest(IDoc.DocumentList documentList)
{
System.out.println("Incoming IDoc list request containing " +
documentList.getNumDocuments() + " documents...");
IDoc.DocumentIterator iterator = documentList.iterator();
IDoc.Document doc = null;
while (iterator.hasNext())
{
doc = iterator.nextDocument();
System.out.println(doc.toXML());
System.out.println("Processing document no. " + doc.getIDocNumber() + "...");
String iDocType = doc.getIDocTypeExtension();
if (iDocType.length() == 0) iDocType = doc.getIDocType();
String filename = "IDOC_" + iDocType + "_" + doc.getIDocNumber() + "_" +
timestampFormat.format(new java.util.Date()) + ".xml";
System.out.print("Storing IDoc as XML file '" + incomingPath + filename + "'...");
doc.writeXML(incomingPath + filename);
System.out.println(" done.");
if (doc.getMessageType().equals("ORDERS")) {
System.out.println("Processing message of type 'ORDERS'...");
processOrder(doc);
} else {
System.out.println("Message of type '" + doc.getMessageType() +
"' won't be processed.");
}
}
}//method handleRequest
/**
* The following 4 methods for transaction management are not implemented
* here in this sample program. For a description on how to implement
* them in real production scenarios please see the JCo API specification
* for the JCO.Server class.
*/
protected boolean onCheckTID(String tid) {
return true;
}//method onCheckTID
protected void onConfirmTID(String tid) {
}//method onConfirmTID
protected void onCommit(String tid) {
}//method onCommit
protected void onRollback(String tid) {
}//method onRollback
}//class MyIDocServer
/**
* Process an IDoc of type ORDERS##.
* Please note that this is only a sample processing that does not reflect
* all possible application data scenarios for ORDERS. There are different
* segment navigation and iteration techniques used within this method.
*/
public static void processOrder(IDoc.Document order)
{
try {
String filename = "ORDER_" + order.getIDocNumber() + "_" +
timestampFormat.format(new java.util.Date()) + ".txt";
System.out.print("Storing IDoc as text file '" + filename + "'...");
PrintWriter out = new PrintWriter(new FileOutputStream(incomingPath + filename));
out.println("General data:");
out.println("-------------");
out.println("IDoc number: " + order.getIDocNumber());
out.println("Partner number: " + order.getSenderPartnerNumber());
out.println("IDoc type: " + order.getIDocType());
out.println("IDoc type extension: " + order.getIDocTypeExtension());
//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.
IDoc.Segment root = order.getRootSegment();
IDoc.Segment seg = null;
//get the document header general data
seg = root.getFirstChild("E1EDK01");
String currency = seg.getString("CURCY");
out.println("/nOrder number: " + seg.getString("BELNR"));
//get the customer (sold-to party)
seg = root.getFirstChild("E1EDKA1", "PARVW", "AG");
if (seg!=null) {
out.println("/nSold-to party:");
out.println("--------------");
writeAddress(out, seg);
}
//get the goods recipient (ship-to party)
seg = root.getFirstChild("E1EDKA1", "PARVW", "WE");
if (seg!=null) {
out.println("/nShip-to party:");
out.println("--------------");
writeAddress(out, seg);
}
//process the order items
IDoc.SegmentIterator orderItems = root.getChildrenIterator("E1EDP01");
out.println("/nOrder items:");
out.println("------------");
IDoc.Segment segItemID = null;
String materialID = null;
String materialText = null;
String priceUnit = null;
while (orderItems.hasNext())
{
//get the next order item
seg = orderItems.nextSegment();
//first try to find segment specifying material number
//used by vendor (first segment field QUALF=002)
segItemID = seg.getFirstChild("E1EDP19", 0, "002");
//if not found try to find segment specifying international
//article number EAN (first segment field QUALF=003)
if (segItemID==null) segItemID = seg.getFirstChild("E1EDP19", 0, "003");
//if not found try to find segment specifying material number
//used by customer (first segment field QUALF=001)
if (segItemID==null) segItemID = seg.getFirstChild("E1EDP19", 0, "001");
//get the material ID and short text
if (segItemID!=null) {
materialID = segItemID.getString(1); //field IDTNR
materialText = segItemID.getString(2); //field KTEXT
} else {
materialID = "unknown";
materialText = "product";
}
//get the ordered quantity and price data
//and output the ordered item
out.print(seg.getString("MENGE") + " "); //quantity
out.print(seg.getString("MENEE") + " "); //unit of measure
out.print(materialID + " " + materialText);
out.print(" ; Price: ");
out.print(seg.getString("VPREI") + " "); //price (net)
out.print(currency + "/");
priceUnit = seg.getString("PEINH"); //price unit
if (!priceUnit.equals("1")) out.print(priceUnit + " ");
out.print(seg.getString("PMENE")); //price unit of measure
out.print(" ; Total Price: ");
out.print(seg.getString("NETWR") + " "); //item value (net)
out.println(currency);
}
//get some totals (if available)
out.println("/nTotals:");
out.println("-------");
seg = root.getFirstChild("E1EDS01");
while (seg!=null) {
switch (seg.getShort("SUMID")) {
case 001: out.println("Number of items: " + seg.getString("SUMME") + " " + seg.getString("SUNIT"));
case 002: out.println("Net document value: " + seg.getString("SUMME") + " " + seg.getString("SUNIT"));
}
seg = seg.getNextSibling("E1EDS01");
}
out.close();
System.out.println(" done.");
}
catch (java.lang.Exception ex) {
System.out.println("Exception occurred: " + ex);
}
}//method processOrder
/**
* Standard method for writing address data extracted from an E1EDKA1 segment
* to a PrintWriter output stream.
*/
public static void writeAddress(PrintWriter out, IDoc.Segment e1edka1)
{
String value = null;
value = e1edka1.getString("PARTN");
if (value.length()>0) out.println("Partner number: " + value + "/n");
value = e1edka1.getString("NAME1");
if (value.length()>0) out.println("Name 1: " + value);
value = e1edka1.getString("NAME2");
if (value.length()>0) out.println("Name 2: " + value);
value = e1edka1.getString("NAME3");
if (value.length()>0) out.println("Name 3: " + value);
value = e1edka1.getString("NAME4");
if (value.length()>0) out.println("Name 4: " + value);
value = e1edka1.getString("STRAS"); //
if (value.length()>0) out.println("Street 1: " + value);
value = e1edka1.getString("STRS2");
if (value.length()>0) out.println("Street 2: " + value);
value = e1edka1.getString("ORT01");
if (value.length()>0) out.println("City: " + value);
value = e1edka1.getString("COUNC");
if (value.length()>0) out.println("County code: " + value);
value = e1edka1.getString("PSTLZ");
if (value.length()>0) out.println("Postal code: " + value);
value = e1edka1.getString("LAND1");
if (value.length()>0) out.println("Country key: " + value);
value = e1edka1.getString("TELF1");
if (value.length()>0) out.println("1st phone: " + value);
value = e1edka1.getString("TELF2");
if (value.length()>0) out.println("2nd phone: " + value);
value = e1edka1.getString("TELFX");
if (value.length()>0) out.println("Fax: " + value);
value = e1edka1.getString("BNAME");
out.println();
if (value.length()>0) out.println("User: " + value);
value = e1edka1.getString("PAORG");
if (value.length()>0) out.println("Org. code: " + value);
value = e1edka1.getString("ORGTX");
if (value.length()>0) out.println("Org. text: " + value);
value = e1edka1.getString("PAGRU");
if (value.length()>0) out.println("Group code: " + value);
}//method writeAddress
/**
* Interface method of JCO.ServerExceptionListener to be notified about
* server exceptions.
*/
public void serverExceptionOccurred(JCO.Server server, java.lang.Exception ex)
{
System.out.println("Server exception occurred: " + ex);
}//method serverExceptionOccurred
/**
* Main method initializing and starting the JCoIDoc.Server.
*/
public static void main(String[] args)
{
try {
//instantiate main class
IDocReceiver myApp = new IDocReceiver();
//add server exception listener to be notified about server exceptions
JCO.addServerExceptionListener(myApp);
//server properties to log on at the gateway server
java.util.Properties srvProps = new java.util.Properties();
srvProps.put("jco.server.gwhost", "B03");
srvProps.put("jco.server.gwserv", "sapgw00");
srvProps.put("jco.server.progid", "IDOCTEST"); // This should match with the one created in Step1
srvProps.put("jco.server.unicode", "0"); // enter "1" for unicode systems
//client properties to log on for repository queries
java.util.Properties clntProps = new java.util.Properties();
clntProps.put("jco.client.client", "500");
clntProps.put("jco.client.user", "UserID");
clntProps.put("jco.client.passwd", "*****");
clntProps.put("jco.client.lang", "EN");
clntProps.put("jco.client.ashost", "B03");
clntProps.put("jco.client.sysnr", "00");
//create a JCo client pool
JCO.addClientPool("MyPool", 5, clntProps);
//create a JCo repository that will be used for querying
//meta data for standard function requests
IRepository jcoRepository = JCO.createRepository("MyJCoRepository", "MyPool");
//create an IDoc repository that will be used for querying
//IDoc meta data
IDoc.Repository idocRepository = JCoIDoc.createRepository("MyIDocRepository", "MyPool");
//create a JCoIDoc.Server instance
MyIDocServer server = new MyIDocServer(srvProps, jcoRepository, idocRepository);
//start the JCoIDoc.Server instance and listen for incoming
//function requests and IDocs
server.start();
System.out.println("Started MyIDocServer.");
System.out.println("MyIDocServer is listening now...");
}
catch ( java.lang.Exception ex ) {
System.out.println("Application error: " + ex);
}
}
}
To Test this you need to login to the R/3 system
Use the Transaction WE19
Select Basic Type and Enter ORDERS05
Click on Execute
Double Click on EDIDC
Fill in the details as follows
lick on Continue.
Click on Standard Outbound Processing
Output expected at the java end
MyIDocServer is listening now...
Incoming IDoc list request containing 1 documents...
Processing document no. 0000000000208036...
Storing IDoc as XML file 'c:/IDOC_ORDERS05_0000000000208036_20081120203757.xml'... done.
Open the file to see the contents received from R/3.
Following is the code needed to send the IDoc from Java to R/3
//Code available with IDoc Samples
package com.bcone.test;
import com.sap.mw.idoc.IDoc;
import com.sap.mw.idoc.jco.JCoIDoc;
import com.sap.mw.jco.JCO;
public class JCoIDocSender
{
public static void main(String[] args)
{
try {
//create a JCo client pool
JCO.addClientPool( "MyPool", //pool name
3, //maximum pool connections
"500", //SAP client
"UserID", //RFC Permission needed for user ID
"*****", //password
"EN", //language
"B03", //app server host name
"00" ); //system number
//create an IDoc repository
IDoc.Repository idocRep = JCoIDoc.createRepository("MyIDocRepository", "MyPool");
//create a new and empty MATMAS02 document
System.out.print("Creating IDoc...");
IDoc.Document doc = JCoIDoc.createDocument(idocRep, "MATMAS02");
//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.setField("MSGFN", "005");
segment.setField("MATNR", "BOXCOOKIES");
segment.setField("ERSDA", "20081101");
segment.setField("ERNAM", "UserID");
segment.setField("PSTAT", "K");
segment.setField("MTART", "FERT");
segment.setField("MBRSH", "M");
//segment.setField("MATKL", "G1113");
segment.setField("MEINS", "PCE");
segment.setField("BLANZ", "000");
segment.setField("BRGEW", "0.550");
segment.setField("NTGEW", "0.000");
segment.setField("GEWEI", "KGM");
segment.setField("VPSTA", "KBG");
//create and add a new and empty child segment of type E1MAKTM
//and fill the segment data
segment = segment.addChild("E1MAKTM");
segment.setField("MSGFN", "005");
segment.setField("SPRAS", "D");
segment.setField("MAKTX", "Box of cookies[DE]");
segment.setField("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.setField("MSGFN", "005");
segment.setField("SPRAS", "E");
segment.setField("MAKTX", "Box of cookies");
segment.setField("SPRAS_ISO", "EN");
//prepare document for sending and set the appropriate control data
doc.setMessageType("MATMAS");
doc.setRecipientPartnerType("LS");
doc.setRecipientPartnerNumber("LSB03");
doc.setSenderPort("JAVIDOC");
doc.setSenderPartnerType("LS");
doc.setSenderPartnerNumber("JAVSYS");
System.out.println(" done.");
//check the whole document's syntax
try {
System.out.print("Checking IDoc syntax...");
doc.checkSyntax();
System.out.println(" done.");
}
catch ( IDoc.Exception ex ) {
System.out.println(" Syntax error: " + ex);
ex.printStackTrace();
System.exit(0);
}
//get a JCo client from previously created client pool
JCO.Client client = JCO.getClient("MyPool");
//create a new transaction ID
String tid = client.createTID();
//send the document to the SAP system asynchronously
System.out.print("Sending IDoc...");
System.out.println(doc.toXML());
client.send(doc, tid);
//confirm the transaction ID
client.confirmTID(tid);
System.out.println(" done.");
//release the JCo client and return it back to the pool
JCO.releaseClient(client);
}
catch ( java.lang.Exception ex ) {
System.out.println("Application error: " + ex);
ex.printStackTrace();
}
}//method main
}
Once this code is executed You will see the following statements in the console.
Creating IDoc... done.
Checking IDoc syntax... done.
done.
Now you can login to the R/3 system and check whether the Material Master is created or not.
Incase if the material is not created use the transaction WE02.
Following should be the status if its successfully posted.
If the status is red, double click on the status record number for the error reason and details.