Tuesday, April 17, 2018

How to call BAPI in SAP from nodejs app

Recently I used nodejs RFC Connector provided by SAP. The module called node-rfc provides bindings for SAP NetWeawer RFC Library. Via the library it is possible to call RFC enabled function modules residing in SAP NetWeaver based ABAP system from nodejs, leveraging SAP Remote Function Call (RFC) protocol. For installation of the module into your nodejs framework see here.

Below I provide two example nodejs apps showcasing possibilities to passing values to BAPI’s parameters like single values, structures and tables.

I think that the node-rfc module is great option how to interface with SAP systems from heavily used nodejs app like in case of web based apps.

You can find both examples on my github:

demo_BAPI_params1.js      usage of table and variable parameter

//demo prg to showcase usage of table and variable parameters of SAP's BAPI while called from nodejs app via SAP/node-rfc nodule
"use strict";
var rfc = require('node-rfc');
var abapSystem = {
    user: 'sap_user',
    passwd: 'sap_user_pwd',
    ashost: 'sap.nodomain',
    sysnr: '01',
    client: '800'
};
var client = new rfc.Client(abapSystem);
var MAX_ROWS = 3;
var SELECTION_RANGE_str = {
               PARAMETER: "USERNAME",
               SIGN:      "I",
               OPTION:    "CP",
               LOW:       "A*"
        };     
var SELECTION_RANGE_tab = [SELECTION_RANGE_str];
       
client.connect(function(err) {
    if (err) {
        return console.error('could not connect to server', err);
    }  
    client.invoke('BAPI_USER_GETLIST', {
                       MAX_ROWS: MAX_ROWS,
                       SELECTION_RANGE: SELECTION_RANGE_tab
        },
        function(err, res) {
            if (err) {
                return console.error('Error invoking BAPI_USER_GETLIST:', err);
            }
               console.log('Result BAPI_USER_GETLIST:', res);
        });   
});

demo_BAPI_params2.js      usage of structure parameter of SAP's BAPI

//demo prg to showcase usage of structure parameter of SAP's BAPI while called from nodejs app via SAP/node-rfc nodule
"use strict";
var rfc = require('node-rfc');
var abapSystem = {
    user: 'sap_user',
    passwd: 'sap_user_pwd',
    ashost: 'sap.nodomain',
    sysnr: '01',
    client: '800'
};
var client = new rfc.Client(abapSystem);
 
client.connect(function(err) {
  if (err) {
    return console.error('could not connect to server', err);
  }
  var IMPORTSTRUCT = {
    RFCDATA1: 'some value of structure field RFCDATA1',
    RFCDATA2: 'some value of structure field RFCDATA2'
  };
  client.invoke('STFC_STRUCTURE',
    { IMPORTSTRUCT: IMPORTSTRUCT },
    function(err, res) {
      if (err) {
        return console.error('Error invoking STFC_STRUCTURE:', err);
      }
      console.log('Result STFC_STRUCTURE:', res);
  });
});

25 comments:

demo said...

Nice blog thank you for your guidance,
I also want to implement SAP BAPI using node-rfc module, but i didn't understand node-rfc module setup how to configure it on machine, would you give me additional information about it?

Please, needful
Thank You.
Moreshwar Dalvi (moreshwardlv@gmail.com)

Martin Maruskin said...

Hi,

installation of node-rfc is described here:

please provide an exact issue that you are facing with node-rfc setup only afterward I can help.

cheers

demo said...


Thank you so much for your reply.

Okay, Let me tell you what I have understood so far,
I have to create web serve using node js on server side, which will call SAP's business functions so that I cant create and update the data using mobile application.

I have downloaded:
> NWRFC_49-20004568.SAR
> SAPCAR_721-20010453.exe

and execute command: >_ SAPCAR_721-20010453.exe -xvf NWRFC_49-20004568.SAR //this is example

> Copied the files from the lib folder to C:\Windows\system32

---------------

then I going to create node js application, were I had installed following package
npm install sapnwrfc (but it dosen't installed correctly)

Is it Correct steps, I had done so far?

Let me know if I am wrong.

Thank you.


demo said...

Hello,
Following are the steps, which I have worked so far.

SAP B1 Connectiviy

Windows 10 64-Bit
Node JS v9.11.2


> SAPCAR_721-20010453.exe
> NWRFC_49-20004568.SAR

unpacked these files by executing command: >_ SAPCAR_721-20010453.exe -xvf NWRFC_49-20004568.SAR
created folder 'nwrfcsdk'

> Moved 'lib' from 'nwrfcsdk' folder to 'C:\Windows\System32'
> updated PATH : C:\Windows\System32\lib;

> node js program:

"use strict";

var express = require('express');
var app = express();

var rfc = require('node-rfc');

var abapSystem = {
ashost: '192.168.0.21',
sysid: '0010000100',
sysnr: '000000000800290944',
user: 'manager',
passwd: '1234',
client: '001',
lang: 'E'
};

var client = new rfc.Client(abapSystem);

app.get('/', function (req, res) {

client.connect(function(err) {
if (err) {
res.send('could not connect to server' + err);
}
else {
res.send('Connected successfully');
}
});
});

app.listen(process.env.PORT);

OUTPUT: could not connect to serverError: LOCATION CPIC (TCP/IP) on local host DESKTOP-U4L78SE with Unicode ERROR partner '192.168.0.21:3300' not reached TIME Tue Nov 27 14:35:49 2018 RELEASE 721 COMPONENT NI (network interface) VERSION 40 RC -10 MODULE nixxi.cpp LINE 3289 DETAIL NiPConnect2: 192.168.0.21:3300 SYSTEM CALL connect ERRNO 10061 ERRNO TEXT WSAECONNREFUSED: Connection refused COUNTER 2


Also, I would like know more about abapSystem object, about its parameter list.

Thank you.

Martin Maruskin said...

SAP NetWeawer RFC Library files extracted from SAP archive doesn't need to be extracted to C:\Windows\system32. You can use any folder that you want. Just you need o make sure the folder is added into variable PATH of the Windows.

Secondly, for installtion of the node-rfc you need to you following command not the one you provided:
npm install node-rfc

Martin Maruskin said...

Error "could not connect to server" means that your SAP instance is not available. Check with people who are responsible for the system. Perhaps is not running...? Perhaps IP address of SAP system isn't correct?

Also these values:
sysid: '0010000100',
sysnr: '000000000800290944',
are not correct. Sysid has always 3 characters. Sysnr is always 2 digit number.

Unknown said...

module.js:682
return process.dlopen(module, path._makeLong(filename));
^

Error: The specified module could not be found.
\\?\A:\node\sap-connecter\node_modules\node-rfc\build\rfc\rfc.node
at Object.Module._extensions..node (module.js:682:18)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object. (A:\node\sap-connecter\node_modules\node-rfc\index.js:6:11)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)

Unknown said...

module.js:682
return process.dlopen(module, path._makeLong(filename));
^

Error: The specified module could not be found.
\\?\A:\node\sap-connecter\node_modules\node-rfc\build\rfc\rfc.node
at Object.Module._extensions..node (module.js:682:18)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object. (A:\node\sap-connecter\node_modules\node-rfc\index.js:6:11)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)

Martin Maruskin said...

Hi Srinath,

regarding an error "The specified module could not be found." just see my other blog Issues while setting up SAP RFC Connector for NodeJS (node-rfc) connector.

You need to make sure that libraries are located in lib folder e.g. "c:\Program Files\nodejs\nwrfcsdk\lib\". There is another folder under lib just move all files to upper folder...

cheers

Unknown said...

Thanks Martin for quick reply, i found the problem i used the wrong nwrfc'sdk' of linux my bad

GnDesigner said...

Hello martin, great blog post
I managed to connect to the server and make some request, bow i'm wondering if i can make more complex queries like JOIN tables, etc.

Thank you

GnDesigner said...

Great Blog entry Martin.
I managed to connect to the server and make some queries, but now I'm wondering if i can create more complex queries like joining tables and how can I get it done
thnk you for your help

Martin Maruskin said...

Hi Designer,

you can use BAPI RFC_READ_TABLE to read DB tables. However, reading directly tables is not recommended way how to interface SAP. Because you may lose business content that the information you read may have.
Normally there is a BAPI created by SAP to read any type of data. So you shall look up first corresponding BAPI and use it.

cheers

Alfonso Perez said...

Hi, I have been following this example

https://mxitgo.group/2018/11/26/exposing-sap-ecc-information-to-node-js-hana-not-required-its-done-through-rfc-so-you-have-the-flexibility-to-create-web-and-mobile-applications/

And you post, but now I have a question: Must I write one file .js for every BAPI or RFC that I´ll need in my application (Android for instance) ?????

I´m trying to develop a server with Sails and I don´t know how to do it ....

Any help ???? For anything more complex for instance if I want to use 50 RFC functions ??
Thansk in advance...

Alfonso Perez said...

Hi Martin,

I have been following this example adn your example

https://mxitgo.group/2018/11/26/exposing-sap-ecc-information-to-node-js-hana-not-required-its-done-through-rfc-so-you-have-the-flexibility-to-create-web-and-mobile-applications/

And I have read data from a RFC functions.

Now I´m trying to write somethin more complex.

I want to wirte a Api Rest with Sails or other framework with 50 RFC´s Abap Functions (o more).

Buy I´m very lost how I can do it, I don´t know if I must to write 50 .js files one for every one RFC or what ????? and How can I start the node server for this ????

Any help ???? Any book or link where find out any idea ?????

Thanks in advance.

Martin Maruskin said...

HI Alfonso,

I do not see necessity to write separate js file for each of BAPI calls.
Your node.js app can have just few js files as per app design. Ad within those files BAPI calls can be implemented.

cheers

Alfonso Perez said...

Hi, I have a questions about node-rfc.

are there any examble how to mapping tables that comes from a function node-rfc to send en Resfull API ???? Or read in node information from outside (for instance in json) and pass it to node-rfc function to execute the function send the data in the tables that node-rfc function need and response in the Resfull API other tables thar SAP has responsed mapping to json, I want json to send information mapping it to the corresponding tables and response the information in the Restfull API that for instance a Android APP, Flutter or Angular has asked for. is it possible ???? Any example or help ????

If I use node-rfc passing a string and response other string is easy, but with tables from SAP to send information to SAP o response the information from one table to outside I´m getting crazy !!!!!

For instance, I have a node-rfc server that recive information from WhatsApp and send the string to SAP using a node-rfc function and push the response from SAP to WhatsApp and it is working perfect.

I´m looking for information or any example but it is impossible to find anything

Thanks in advance.

Alfonso Perez said...

Hi, I have a questions about node-rfc.

are there any examble how to mapping tables that comes from a function node-rfc to send en Resfull API ???? Or read in node information from outside (for instance in json) and pass it to node-rfc function to execute the function send the data in the tables that node-rfc function need and response in the Resfull API other tables thar SAP has responsed mapping to json, I want json to send information mapping it to the corresponding tables and response the information in the Restfull API that for instance a Android APP, Flutter or Angular has asked for. is it possible ???? Any example or help ????

If I use node-rfc passing a string and response other string is easy, but with tables from SAP to send information to SAP o response the information from one table to outside I´m getting crazy !!!!!

For instance, I have a node-rfc server that recive information from WhatsApp and send the string to SAP using a node-rfc function and push the response from SAP to WhatsApp and it is working perfect.

I´m looking for information or any example but it is impossible to find anything

Thanks in advance.

Martin Maruskin said...

Hi Alfonso,

basically each of SAP's BAPI (or remote function module) has its own interface (import/export/changing/table parameters). Thus you have to evaluate each of the BAPI's interface and make your node-rfc function call appropriate.

I understand that your issue is while processing tables as parameters of the BAPI. For that I could theoretically leverage some of the BAPI that describes interface of other BAPI like /SDF/GEN_FUNCS_FUNC_INFO_GET.

What is the BAPI that you have a problem to call it with node-rfc?

cheers

online shopping said...

DATA lv_destination TYPE char10.

CASE sy-sysid+2(1).
WHEN 'P'.
lv_destination = 'K0P_040'.
WHEN OTHERS.
lv_destination = 'NONE'.
ENDCASE.

CALL FUNCTION 'ZWF_List_User_Tasks'
DESTINATION lv_destination
EXPORTING
i_user = lv_user
IMPORTING
et_approval_requests = lt_approval_requests.

This is ABAP program in which calling function module with RFC TARGET SYSTEM = 'K0P_040'

clientEH8.invoke('BAPI_COMPANYCODE_GETDETAIL', {
"COMPANYCODEID": "1000",
},

function (err, res)
{

}
});

How to pass RFC TARGET SYSTEM = 'K0P_040' for this node js program?

Martin Maruskin said...

HI online shopping,

your question is more javascript related question rather SAP one :)
I believe you can declare the variable for rfc target system e.g.:

destination = "Volvo";

cheers
m./

online shopping said...

Hi Martin,
Thanks for your response.
destination = "Volvo"; where we should provide in program?

Martin Maruskin said...

HI online shopping,

seems blogging platform removed part of my comments. Not sure how VOLVE got into the my comment. You need to put that statement for a new javascript variable somewhere before a call of BAPI function (clientEH8.invoke). But whole new variable should be declared something like like:

var lv_destination = 'K0P_040';

or

let lv_destination= "K0P_040";

online shopping said...

where need to pass lv_destination for invoke method in nodejs program? this is my million dollar question

Martin Maruskin said...

Variable lv_destination is not to be passed to node rfc call. That variable is only used in ABAP system in case there is a need to call function module from one SAP system to another one.
See above in my blog's example. You only need to provide parameters for client.invoke call of the BAPI (remote function module) in case the particular BAPI you are calling has some parameters.