Skip to content

SAP RFC Integration

1 Overview

In SAP systems, the capability for remote calls is provided by the RFC (Remote Function Call) interface system. RFC allows calling between two SAP systems (R/3 or R/2), or between an SAP system and a non-SAP system.

2 How Informat Calls SAP RFC Functions

2.1 Call SAP RFC Functions via Java Extension Library

Calling Method

java
package informat.library.poc;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sap.conn.jco.JCo;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoField;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterList;
import com.sap.conn.jco.ext.DestinationDataProvider;

import informat.library.utils.JSONUtil;

public class SapService {
	//
	private static Logger logger=LoggerFactory.getLogger(SapService.class);
	//
	public static String getVersion() {
		return JCo.getVersion();
	}

	public static void registerDestinationDataProvider(String destinationName, Map<String,String> properties) {
		logger.info("registerDestinationDataProvider destinationName:{}",
			destinationName, JSONUtil.toJson(properties));
		Properties props=new Properties();
		if(properties!=null) {
			properties.forEach((k,v)->{
				props.setProperty(k,v);
			});
		}
		com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(new CustomDestinationDataProvider(destinationName, props));

	}

	// Universal SAP function call method
	public static SapFunctionResult callSapFunction(String destinationName, // SAP destination name (e.g., "SAP_DEST")
			String functionName, // Name of the function module to call
			Map<String, Object> inputs, // Input parameter key-value pairs
			List<String> outputTables // Array of output table names to return (optional)
	) throws JCoException {
		logger.info("callSapFunction destinationName:{}, functionName:{}, inputs:{}, outputTables:{}",
			destinationName, functionName, JSONUtil.toJson(inputs), JSONUtil.toJson(outputTables));
		JCoDestination destination = JCoDestinationManager.getDestination(destinationName);
		JCoFunction function = destination.getRepository().getFunction(functionName);
		if (function == null) {
			throw new RuntimeException("SAP function " + functionName + " does not exist");
		}

		// Set input parameters
		if (inputs != null) {
			JCoParameterList importParams = function.getImportParameterList();
			inputs.forEach((k, v) -> importParams.setValue(k, v));
		}

		// Execute function call
		function.execute(destination);

		// Process return results
		SapFunctionResult result = new SapFunctionResult();

		// Get export parameters
		JCoParameterList exportParams = function.getExportParameterList();
		if (exportParams != null) {
			for (JCoField param : exportParams) {
				result.addExportParam(param.getName(), param.getValue());
			}
		}

		// Process output tables (get as needed)
		if (outputTables != null) {
			JCoParameterList tables = function.getTableParameterList();
			for (String tableName : outputTables) {
				if (tables.isActive(tableName)) {
					result.addOutputTable(tableName, tables.getTable(tableName));
				}
			}
		}
		logger.info("callSapFunction result:{}", JSONUtil.toJson(result));
		return result;
	}

	//
	public static void main(String[] args) throws JCoException {
		System.out.println(JCo.getVersion());
		Map<String,String> props = new HashMap<>();
		props.put(DestinationDataProvider.JCO_ASHOST, "your_sap_host"); // SAP server address
		props.put(DestinationDataProvider.JCO_SYSNR, "00"); // System number
		props.put(DestinationDataProvider.JCO_CLIENT, "100"); // Client number
		props.put(DestinationDataProvider.JCO_USER, "username"); // Username
		props.put(DestinationDataProvider.JCO_PASSWD, "password"); // Password
		props.put(DestinationDataProvider.JCO_LANG, "en"); // Language
		props.put(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
		props.put(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
		//
		String destinationName = "SAP_DEST";
		registerDestinationDataProvider(destinationName, props);
		Map<String, Object> inputs = new HashMap<>();
		// 3. Set input parameters
		inputs.put("AUART", "ZOR1");
		inputs.put("ZOAMWLXX", "20_1.05.01.10455");
		inputs.put("KUNSP", "100689");
		//
		List<String> outputTables = List.of( "OT_DATA", "OTHER_TABLE" );
		SapFunctionResult result=callSapFunction(destinationName, "ZFM_SD051", inputs, outputTables);
		System.out.println(JSONUtil.toJson(result));
	}
}

2.2 Package the Java Project and Upload to Informat Application Extension Library

2.3 Informat Script Calls SAP RFC Functions

Informat scripts call the Java extension library through informat.system.invokeLibrary to implement calling SAP RFC functions

js
informat.system.invokeLibrary("saplibrary", "informat.library.poc.SapService", "registerDestinationDataProvider", [
  "sap_test1",
  {
    "jco.client.ashost": "192.168.x.x",
    "jco.client.sysnr": "00",
    "jco.client.client": "800",
    "jco.client.user": "user",
    "jco.client.passwd": "password",
    "jco.client.lang": "en",
    "jco.destination.pool_capacity": "3",
    "jco.destination.peak_limit": "10",
  },
]);

let result = informat.system.invokeLibrary("saplibrary", "informat.library.poc.SapService", "callSapFunction", ["sap_test1", "ZFM_SD051", { AUART: "ZOR1" }, ["OT_DATA", "OTHER_TABLE"]]);
console.log("result", result);

SapFunctionResult Structure

java
public class SapFunctionResult {
	public Map<String, Object> exportParams = new HashMap<>();
	public Map<String, JCoTable> outputTables = new HashMap<>();
}