Send IDoc (Flat File/XML) to SAP System using JCo


In one of my recent projects I had to simulate an external application sending IDocs to SAP PI/PO with tRFC protocol. I decided to use JCo library to implement the scenario. Below you can find the Java code which I developed for that purpose. This code was used just for testing purposes, so test it properly before using it in your production environment.

Prerequisites

  1. Basic knowledge of Java language
  2. Basic knowledge of Eclipse or any other Java IDE
  3. SAPJCo and SAPIDoc libraries (JARs). JARs can be downloaded from SAP official SAP Java Connector site or from “less official” repositories like the following: SAPJCo and SAPIDoc

Setting Up a Project (Eclipse)

  1. Create a regular Java Project (I used Java 8 JRE) and add sapjco3.jar and sapidoc3.jar to the project’s Build Path (I created a User Library named: SAP JCo)
  2. Create a new class named MyJCoClient and copy the following code:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package pl.indevo.jco.idoc;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import com.sap.conn.idoc.IDocDocumentList;
import com.sap.conn.idoc.IDocFactory;
import com.sap.conn.idoc.IDocParseException;
import com.sap.conn.idoc.IDocRepository;
import com.sap.conn.idoc.IDocXMLProcessor;
import com.sap.conn.idoc.jco.JCoIDoc;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoRecord;
import com.sap.conn.jco.JCoRecordMetaData;
import com.sap.conn.jco.JCoTable;

public class MyJCoClient {

	private String destinationName;
	
	public String getDestinationName() {
		return destinationName;
	}

	public void setDestinationName(String destinationName) {
		this.destinationName = destinationName;
	}

	public static void main(String[] args) {
		try {
			MyJCoClient client = new MyJCoClient();
			client.setDestinationName("system");
			client.sendIDocFlat("IDOC_FLAT.txt");
		} catch (Exception e) {
			System.err.println("Exception: " + e.getMessage());
		}
	}

	void ping() throws JCoException {
		JCoDestination destination = JCoDestinationManager.getDestination(getDestinationName());
		System.out.println("Sending ping...");
		destination.ping();
		System.out.println("Ping OK");
		System.out.println("Attributes:");
		System.out.println(destination.getAttributes());
		System.out.println();
	}

	void sendIDocXML(String fileName) throws JCoException, IDocParseException, FileNotFoundException, IOException {
		JCoDestination destination = JCoDestinationManager.getDestination(getDestinationName());
		IDocRepository iDocRepository = JCoIDoc.getIDocRepository(destination);
		String tid = destination.createTID();
		IDocFactory iDocFactory = JCoIDoc.getIDocFactory();
		// a) create new idoc
		// IDocDocument doc = iDocFactory.createIDocDocument(iDocRepository,"ORDERS05");
		// IDocSegment segment = doc.getRootSegment();
		// segment = segment.addChild("E1EDK01");
		// ... and so on. See IDoc Specification ...
		// JCoIDoc.send(doc, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);

		// b) use an existing xml file
		IDocXMLProcessor processor = iDocFactory.getIDocXMLProcessor();
		IDocDocumentList iDocList = processor.parse(iDocRepository, new BufferedReader(new FileReader(fileName)));
		JCoIDoc.send(iDocList, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);
		destination.confirmTID(tid);

		System.out.println("IDoc delivered");
	}

	void sendIDocFlat(String filepath) throws JCoException, IOException {		
		JCoDestination destination = JCoDestinationManager.getDestination(getDestinationName());
		JCoFunction function = destination.getRepository().getFunction("IDOC_INBOUND_ASYNCHRONOUS");

		if (function == null) {
			throw new RuntimeException("IDOC_INBOUND_ASYNCHRONOUS not found in the system");
		}
		JCoTable idocControl = function.getTableParameterList().getTable("IDOC_CONTROL_REC_40");
		JCoTable idocData = function.getTableParameterList().getTable("IDOC_DATA_REC_40");
		parseFlatFileIDoc(filepath, idocControl, idocData);		

		String tid = destination.createTID();
		function.execute(destination, tid);
		destination.confirmTID(tid);

		System.out.println("IDoc delivered");
	}

	void parseFlatFileIDoc(String filepath, JCoTable idocControl, JCoTable idocData) throws IOException{
		BufferedReader br = new BufferedReader(new FileReader(filepath));

		String line;
		int docnum = 0;

		while ((line = br.readLine()) != null) {
			String tabname = line.substring(0, Math.min(10, line.length())).trim();
			if (tabname.equals("EDI_DC40")) { // Control Segment
				docnum++;
				idocControl.appendRow();
				fillSegmentFromText(idocControl, line);
				// comment out if DOCNUM is present in the IDoc file
				idocControl.setValue("DOCNUM", String.format("%010d", docnum));

			} else { // Data Segments
				idocData.appendRow();
				fillSegmentFromText(idocData, line);
				// comment out if DOCNUM is present in the IDoc file
				idocData.setValue("DOCNUM", String.format("%010d", docnum));
			}
		}
		br.close();		
	}
	
	void fillSegmentFromText(JCoRecord record, String text) {
		JCoRecordMetaData meta = (JCoRecordMetaData) record.getMetaData();
		int startIndex;
		int endIndex;
		for (int j = 0; j < meta.getFieldCount(); j++) {
			startIndex = meta.getByteOffset(j);
			endIndex = startIndex + meta.getLength(j);
			endIndex = endIndex > text.length() ? text.length() : endIndex;
			record.setValue(meta.getName(j), text.substring(startIndex, endIndex));
		}

	}
}
  1. Create a text file named system.jcoDestination in your project’s main directory (it’s used by JCoDestinationManager). The content of the file depends on your scenario (see SAP documentation for method createClient for a full list of possible properties):

Direct connection to an ABAP-based system (single instance)

jco.client.client=[system client]
jco.client.ashost=[application server host]
jco.client.user=[user name]
jco.client.passwd=[password]

Connection to an ABAP-based system (Message Server)

jco.client.client=[system client]
jco.client.mshost=[message server host]
jco.client.msserv=[message server service]
jco.client.group=[server group]
jco.client.user=[user name]
jco.client.passwd=[password]

Connection to an ABAP-based system through RFC Gateway

jco.client.gwhost=[gateway host]
jco.client.gwserv=[gateway service]
jco.client.tpname=[registered program name]

Connection to a Java-based system through RFC Gateway (e.g. SAP PI/PO)

jco.client.gwhost=[gateway host]
jco.client.gwserv=[gateway service]
jco.client.tpname=[registered program name]
jco.destination.repository_destination=[destination to a SAP ABAP system with metadata]
INFORMATION

For security reasons, communication with non-ABAP RFC clients is not allowed for SAP Java systems by default. To enable it, you need to set the system’s VM parameter jco.allow_non_abap_partner to ‘1′, and restart the server. See SAP note 1729203 for details.

  1. Copy your IDoc file (either XML or a Flat File) to the project’s main directory (for XML change method in line 38 to sendIDocXML)
  2. Run the application as Java Application

Still cannot solve your issue?

Our experts are always ready to help.
Get in touch and ask for a consulting offer.