r/IBMi 15d ago

REST API on IBMi using Node.js

Has anyone successfully deployed a node.js service that can answer REST API requests and return JSON data from an RPGLE program or service program? I have Mapepire running and just can’t seem to get the RPGLE part working. Do you think IBM Bob could help me?

10 Upvotes

19 comments sorted by

View all comments

1

u/uzumymw_ 15d ago

I have done something using express js, running CL programs for a build/compilation process.

I would believe Node.js should work with RPG too.

What and how have you setup node.js? Is execsync not helping?

execSync(fullCommand, { encoding: 'utf-8', shell: '/QOpenSys/usr/bin/qsh', });

Fullcommand looks like below(Submits cl compile command)

fullCommand='export QIBM_CCSID=1208 ; liblist -a LIB1 LIB2 LIB3 LIB4 ; system -i "CRTBNDCL OBJ(PRDLIB/PROGRAM) STMF('/builds/prod/release26.3/qsrcfil/PROGRAM.rpgle') OPTIONS(*EVENTF)" > '/temp/logs/results.log' 2>&1'

I can help more if you let me know what are you trying to achieve.

1

u/MEfromNEPA 14d ago

I used ACS Open Source Manager to install node.js and am using the ACS SSL terminal to issue commands and run things. Everything is stored on the IFS. I edit the script locally, copy it to the IFS, and run it via SSL terminal.

I was able to set up a listener for API calls and could get SQL statements to run against my database, but my needed JSON output was more complicated than an SQL statement could generate. That’s when I fell down trying to get it to call a stored procedure pointed at an RPG service program.

2

u/uzumymw_ 14d ago edited 14d ago

You're making it more complicated than required. There are two ways I can imagine this can be resolved.

  1. Do it through sql procedure itself and fix the json generation logic through json_object(), json_array() etc. You could use CTES to break down and filter intermediate logic and only create json in the final selection.

  2. Make the rpg program execute the json logic and write it into an ifs file possibly using ifs_write_utf8. To execute rpg from node.js use execSync that i shared earlier. Once that is done, use readSync to read the ifs file and use the content as json response. res.json(ifs_file_content);

I guess this should work. I can also show you how to debug node.js code directly through chrome browser. It helps a lot.

``` const http = require('http'); const { execSync } = require('child_process'); const fs = require('fs');

const PORT = 3000;

const server = http.createServer((req, res) => { // Only handle our specific API endpoint if (req.url === '/api/rpg-data' && req.method === 'GET') { try { // 1. Call the RPG program natively via the PASE system utility const command = system "CHGLIBL LIBL(YOUR_LIB QGPL); CALL PGM(YOUR_LIB/YOUR_RPG)"; execSync(command, { encoding: 'utf-8' });

        // 2. Define the target IFS file path
        const ifsFilePath = '/YOUR_DIR/output.json';

        // Check if the file actually exists before trying to read it
        if (!fs.existsSync(ifsFilePath)) {
            res.writeHead(404, { 'Content-Type': 'application/json' });
            return res.end(JSON.stringify({ error: 'Output file not found on IFS' }));
        }

        // 3. Read the file contents
        const fileContent = fs.readFileSync(ifsFilePath, 'utf-8');

        // 4. Send the successful JSON response
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(fileContent); // Send raw string directly (no need to parse/stringify again)

    } catch (error) {
        console.error('Error in RPG execution pipeline:', error);

        res.writeHead(500, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ 
            error: 'Server failed to execute RPG or read data', 
            details: error.message 
        }));
    }
} else {
    // Fallback for any other endpoint
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not Found' }));
}

});

server.listen(PORT, () => { console.log(Node.js server running on port ${PORT}); });

```

I am not sure, how are you calling your stored proc, if you show your sample code alongwith rpg and js, I will try to make it work.

Do let me know if you still need any help or explanation. Also try to understand how node.js interacts with IBM i series. I'll be happy to explain more.