Technical Articles
Calling ABAP from NodeJS even easier
Calling ABAP BAPIs and remote enabled function modules (RFMs) from NodeJS is already easy:
const nodeRfc = require('node-rfc');
const pool = new nodeRfc.Pool({ connectionParameters: { dest: "MME" }});
(async () => {
try {
const client = await pool.acquire();
const result = await client.call("BAPI_USER_GET_DETAIL", {
USERNAME: "DEMO",
});
console.log(result);
} catch (err) {
console.error(err);
}
})();
In this particular case, BAPI returns the information about ABAP user, based on one single input parameter, the USERNAME variable.
RFM input/output parameters can be also structures and tables,with hundred or more data fields. Some parameters may be mandatory, others are optional. Some variables, or structure/table fields may have ABAP Conversion Exits, which are not automatically triggered in RFC communication. RFM may return errors for the same input parameters which do work in ABAP transactions, like SE37 for example (see 206068 – Error when calling a BAPI from an external RFC client).
Assuming the Conversion Exits are fixed on ABAP side, complex BAPIs and RFMs parameters’ can be a challenge for NodeJS developer. One has to check which fields are mandatory, which default values used for optional fields, field technical format and so on.
The abap CLI utility helps here, by generating a NodeJS source code for a given ABAP RFM call. All data structures are exposed, with metadata information and default technical initialisers, at field level.
Let try it with one complex RFM, like BAPI_SALESORDER_CREATEFROMDAT2 for example. First create the sapnwrfc.ini file, with the destination and connection parameters of your test system
sapnwrfc.ini
DEST=MME
USER=demo
PASSWD=welcome
ASHOST=myhost
SYSNR=00
CLIENT=620
LANG=EN
Then you can invoke the abap CLI for any remote enabled function module, to create the NodeJS call template of that function module in your backend system:
$ npm -g abap-api-tools
$ abap call MME BAPI_SALESORDER_CREATEFROMDAT2
The output for BAPI_SALESORDER_CREATEFROMDAT2 is echoed to console and, if the -s switch added, saved in a single local file. The full output (“call template”) has ca 1,300 lines of code, structured as follows:
The file starts with the top-level RFM call structure, with optional parameters commented out, using only mandatory parameters ORDER_HEADER_IN and ORDER_PARTNERS:
//
// BAPI_SALESORDER_CREATEFROMDAT2
//
let params = {
// IMPORT PARAMETERS
ORDER_HEADER_IN : {}, // BAPISDHD1 Order Header
//BEHAVE_WHEN_ERROR : "", // CHAR (1) Error Handling
//BINARY_RELATIONSHIPTYPE : "", // CHAR (4) Binary Relationship Type (Private)
//CONVERT : "", // CHAR (1) Conversion of Partner Function + Order Type
//INT_NUMBER_ASSIGNMENT : "", // CHAR (1) Internal Item Number Assignment
//LOGIC_SWITCH : {}, // BAPISDLS Internal Control Parameter
//ORDER_HEADER_INX : {}, // BAPISDHD1X Sales Order Check List
//SALESDOCUMENTIN : "", // CHAR (10) ALPHA=ALPHA Sales and Distribution Document Number
//SENDER : {}, // BAPI_SENDER Logical System - Sender
//TESTRUN : "", // CHAR (1) Test Run
// TABLE PARAMETERS
ORDER_PARTNERS : [], // BAPIPARNR Document Partner
//EXTENSIONEX : [], // BAPIPAREX Reference Structure for BAPI Parameters ExtensionIn/ExtensionOut
//EXTENSIONIN : [], // BAPIPAREX Customer Enhancement for VBAK, VBAP, VBEP
//ORDER_CCARD : [], // BAPICCARD Credit Card Data
//ORDER_CFGS_BLOB : [], // BAPICUBLB Configuration: BLOB Internal Data (SCE)
//ORDER_CFGS_INST : [], // BAPICUINS Configuration: Instances
//ORDER_CFGS_PART_OF : [], // BAPICUPRT Configuration: Part-of Specifications
//ORDER_CFGS_REF : [], // BAPICUCFG Configuration: Reference Data
//ORDER_CFGS_REFINST : [], // BAPICUREF Configuration: Reference Item / Instance
//ORDER_CFGS_VALUE : [], // BAPICUVAL Configuration: Characteristic Values
//ORDER_CFGS_VK : [], // BAPICUVK Configuration: Variant Condition Key
//ORDER_CONDITIONS_IN : [], // BAPICOND Conditions
//ORDER_CONDITIONS_INX : [], // BAPICONDX Conditions Checkbox
//ORDER_ITEMS_IN : [], // BAPISDITM Item Data
//ORDER_ITEMS_INX : [], // BAPISDITMX Item Data Checkbox
//ORDER_KEYS : [], // BAPISDKEY Output Table of Reference Keys
//ORDER_SCHEDULES_IN : [], // BAPISCHDL Schedule Line Data
//ORDER_SCHEDULES_INX : [], // BAPISCHDLX Checkbox Schedule Line Data
//ORDER_TEXT : [], // BAPISDTEXT Texts
//PARTNERADDRESSES : [], // BAPIADDR1 BAPI Reference Structure for Addresses (Org./Company)
//RETURN : [], // BAPIRET2 Return Messages
};
result = await client.call("BAPI_SALESORDER_CREATEFROMDAT2", params);
Parameters initialised with NodeJS scalars, like integer zero or empty string are ABAP variables, like BEHAVE_WHEN_ERROR. Parameters initialised with empty NodeJS structures are ABAP structures (ORDER_HEADER_IN) and those initialised with empty NodeJS arrays are ABAP tables, like ORDER_PARTNERS.
If Conversion-Exit is attached to data field, the ALPHA comment with Conversion-Exit name is added in comment field, just as a reminder for ABAP developer to add the Conversion Exit in ABAP RFM wrapper. This can be also helpful in troubleshooting.
The first section covers all RFM parameters and ends with the RFM call statement.
Structure and table parameters are in detail covered in the rest of call template output. If the LOGIC_SWITCH parameter structure in required in RFM call, you can search for the BAPISDLS type given in a LOGIC_SWITCH parameter comment and find the field level initialisation of that structure parameter:
// LOGIC_SWITCH BAPISDLS Internal Control Parameter
let LOGIC_SWITCH = {}; // BAPISDLS Internal Control Parameter
let BAPISDLS = {
ADDR_CHECK : "", // CHAR (1) Single-Character Flag
ATP_WRKMOD : "", // CHAR (1) ATP session: Pick up result / new determination APO-ATP
COND_HANDL : "", // CHAR (1) Selection: Condition lines handling (SD document change)
NOSTRUCTURE : "", // CHAR (1) Checkbox
PRICING : "", // CHAR (1) Pricing type
SCHEDULING : "", // CHAR (1) Single-Character Flag
};
The same with the credit card table parameter ORDER_CCARD of the BAPICCARD data type:
// ORDER_CCARD BAPICCARD Credit Card Data
let ORDER_CCARD = []; // BAPICCARD Credit Card Data
let BAPICCARD = {
AMOUNTCHAN : "", // CHAR (1) Payment cards: Amount changed
AUTHORTYPE : "", // CHAR (1) Payment cards: Authorization type
CC_LIMITED : "", // CHAR (1) Payment cards: Limit amount
CC_SEQ_NO : "", // CHAR (10) Payment cards: Payment card suffix
DATAORIGIN : "", // CHAR (1) Payment cards: Entry mode
PRE_AUTH : "", // CHAR (1) Payment cards: Preauthorization
RADRCHECK1 : "", // CHAR (4) Payment Cards: Result of Address Check (Address Result)
RADRCHECK2 : "", // CHAR (4) Payment Cards: Result of Address Check (Address Approval)
RADRCHECK3 : "", // CHAR (4) Payment Cards: Result of Address Check (ZIP Code Result)
RCARDCHECK : "", // CHAR (4) Payment cards: Result of card check (response code)
};
The utility can be used independent of the Fundamental Library for ABAP, to accelerate the development and troubleshooting of NodeJS applications working directly with ABAP data. It works with the any ABAP BAPI or RFM and the output can be used also for Python or Java applications, with minimum post-processing in a text-editor.
Feel free to try, feedback welcome.
It's nice that this is available, but from an architecture point of view I would still prefer to wrap the function in an oData service. Or am I missing some needs?
Anyway, good to know that this is also possible. Thanks for the insights!
The utility is for people already using node-rfc, in scenarios like other ABAP Connectors::
https://support.sap.com/en/product/connectors.html
Also experimenting with low-code ABAP web applications, with new and old systems, hybrid systems etc:
https://blogs.sap.com/2020/08/23/fundamental-library-for-abap/
Hello Srdjan Boskovic,
I am trying to use this in my Cloud Application Programming Model project, trying to call BAPI from SRV layer.
When i tried deploying my MTAR file to Cloud Foundry, its giving error - npm ERR! Failed at the node-rfc@2.4.0 install script.
When i checked some other blogs, saw one comment from you -
Please try with the latest node-rfc 2.4.0, not the 2.3.0 version.
Which is your node version?
The log shows 12.14, which is not supported. Should be at least 12.17: https://github.com/SAP/node-rfc/blob/master/package.json#L11
My Node version is -
User: TestProj $ node -v
v10.23.1
user: TestProj $
Is there any workaround for this to work with lower node versions ? I doubt if we will be able to upgrade node version.
Regards,
Mahesh Z.
Hi mahesh zeple ,
the node-rfc works also on lower LTS versions, only the build from source is restricted by N-API support matrix to
Unless the engine-strict config flag set in your environment, the installation is not affected by this restriction.
The node-rfc is not supported in Cloud Foundry environment and there is one open improvement request: https://influence.sap.com/sap/ino/#/idea/262169
The error might be therefore related to something else and it would help if you can share the error log.
Just tested with 10.23.1 and here the log:
Hello,
Yes , I am also taking somewhat similar error when i run it locally.
Thanks ,
Mahesh Z.
Is hard to guess without the error log/output and more info on environment. You can also create a GitHub issue, with more details there.
Hello Srdjan,
Getting below error while starting the localhost from run config itself -
[ERROR] libsapnwrfc.so: cannot open shared object file: No such file or directory
environment: {
"platform": {
"name": "linux",
"arch": "x64",
"release": "5.4.0-5-cloud-amd64"
},
"env": {
"SAPNWRFC_HOME": "",
"RFC_INI": ""
},
"versions": {
"node": "14.16.0",
"v8": "8.4.371.19-node.18",
"v8": "8.4.371.19-node.18",
"uv": "1.40.0",
"zlib": "1.2.11",
"brotli": "1.0.9",
"ares": "1.16.1",
"modules": "83",
"nghttp2": "1.41.0",
"napi": "7",
"llhttp": "2.1.3",
"openssl": "1.1.1j",
"cldr": "37.0",
"icu": "67.1",
"tz": "2020a",
"unicode": "13.0"
}
}
at Object.Module._extensions..node (internal/modules/cjs/loader.js:1122:18)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object. (/home/user/projects/emailpoc/node_modules/node-rfc/lib/wrapper/noderfc-bindings.js:36:49)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object. (/home/user/projects/emailpoc/node_modules/node-rfc/lib/index.js:16:14)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
Process exited with code 1
Thanks ,
Mahesh Zeple.
Did you install SAP NWRFC SDK following the installtion guide: https://github.com/SAP/node-rfc/blob/main/doc/installation.md ?
is there a working github example? POST example seems like dangerous. How about bapi_salesorder_getlist example.
Here it is: https://github.com/SAP-samples/node-rfc-samples/tree/main/integration/express
Hi,
I am new to node.js and getting the following error while trying to run this.
(node:2844) UnhandledPromiseRejectionWarning: TypeError: fs_1.default.rmSync is not a function
at Object.rmDir (/Users/<user>/.nvm/versions/node/v12.18.4/lib/node_modules/abap-api-tools/dist/utils.js:69:18)
at Backend.annotations_clean (/Users/<user>/.nvm/versions/node/v12.18.4/lib/node_modules/abap-api-tools/dist/backend.js:609:17)
at Backend.parse (/Users/<user>/.nvm/versions/node/v12.18.4/lib/node_modules/abap-api-tools/dist/backend.js:346:18)
at async CliHandler.run (/Users/<user>/.nvm/versions/node/v12.18.4/lib/node_modules/abap-api-tools/dist/abap.js:63:35)
(node:2844) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:2844) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Any idea how this could be resolved?
Hi,
the issue is related to abap-api-tools.
You can create an issue here: https://github.com/SAP/fundamental-tools/issues and describe steps how to reproduce.
Kind regards, srdjan