Tip 4: How to debug a low-code module by converting to "real" PJS code





In PJS 6.0, you can debug low-code using the Designer IDE. This tip documents a different way to debug a low-code module, by "converting" it to "real" PJS code, so that you can see all the details in the PJS code generated from the low-code JSON specs. It's also a good way to learn "when I use a plugin, what does that plugin do behind the scenes, what actual 'real' PJS code does it run?".



Example of a low-code module with a bug

  • Navigate to the workspace "pjstips".

  • Click New/Module File.

  • Click Edit/Source, to bring up the Source view.

  • Clear the current default code, and enter the code below.



  • pjstips_04_1.module.json

    { "routines": [ { "name": "routine1", "inputs": [ { "type": "decimal", "ibmiLength": 4, "name": "custno", "ibmiDecimals": 0 } ], "outputs": [ { "type": "string", "ibmiLength": 30, "name": "name" } ], "steps": [ { "text": "Consume REST service", "answers": { "plugin": "Custom:web-service", "uri": "http://localhost:8081/run/pjstips/pjstips_02_3", "method": "POST", "headers": "{\"Content-Type\": \"application/x-www-form-urlencoded\"}", "body": "{\n \"custno\": input[\"custno\"]\n}", "json": true, "auth": "", "capture_response": true, "capture_on_error": false, "capture_as": "Value", "specific_property": "", "destination": "Work variable", "work_variable": "myres" } }, { "text": "Set Module output", "answers": { "plugin": "Program Data:set-module-output", "module-output-values": { "name": "myres[\"name\"]" } } } ] } ] }



  • Click Edit/Design, to bring up the Design view.

  • If needed, in the "Consume REST service" step, change the Endpoint URL to point to the correct host/port.

  • Click Home/Save As, and save as pjstips_04_1.module.json.

  • You've created a low-code module, as shown below, with a routine named "routine1" that:

    • Takes an input parameter of "custno".

    • Uses plug "Consume REST service" to issue a POST request to URL http://localhost:8081/run/pjstips/pjstips_02_3 (created in a previous example).

    • The input "custno" is specified in the "body" of the POST request.

    • The returned JSON object from the REST web service is saved in a work variable named "myres".

    • The value of myres["name"] is used to set the output value output["name"].

    • But, it has a bug; we'll learn how to debug this problem.





  • You can call this low-module from another low-code module, from another "regular" (i.e. NOT low-code) PJS module, or from an RPG program. To call it from an RPG program, use the code generated in the panel "IBM i Call Interface" panel.





  • Below is an example, there the input custno is set to 1234 to pass to the low-code module, which calls the REST service to get the customer name, which is then returned to the RPG program, which is then displayed on the screen.

PJSTIPS041.rpgle
**free Dcl-PR PJSCALL ExtPgm; ParmType Char(30) Const; ModuleID VarUCS2(500) Const; RoutineName VarUCS2(70) Const; InputParms Char(16773104) Const Options(*Varsize:*Omit:*NoPass); InputParmSize Int(10) Const Options(*Omit:*NoPass); OutputParms Char(16773104) Options(*Varsize:*Omit:*NoPass); OutputParmSize Int(10) Const Options(*Omit:*NoPass); End-PR; Dcl-DS InputDS Qualified Inz; custno Zoned(4: 0); End-DS; Dcl-DS OutputDS Qualified Inz; name VarChar(30); End-DS; InputDS.custno = 1234; // pass input to the low-code module in "InputDS" Monitor; PJSCALL('*MODULE' : 'pjstips:pjstips_04_1.module.json' : 'routine1' : InputDS : %Size(InputDS) : OutputDS : %Size(OutputDS) ); On-Error; EndMon; dsply OutputDS.name; // output from the low-code module in "OutputDS" *inlr = *on; return;



  • When you use the RPG program to call this low-code module, you'll get an error similar to this:

2023-01-12 17:18:17 | Session 15A8388C315188097F933049F61E80008712FB286E1C92B80FF342A2E9F69167 | User TNGUYEN | Job TNGUYENAA | Job# 685033 null: TypeError: str.replace is not a function message: "str.replace is not a function" stack: "TypeError: str.replace is not a function at Querystring.rfc3986 (c:\Users\Tien Nguyen\Desktop\profoundjs\node_modules\request\lib\querystring.js:43:14) at Request.json (c:\Users\Tien Nguyen\Desktop\profoundjs\node_modules\request\request.js:1287:30) at Request.init (c:\Users\Tien Nguyen\Desktop\profoundjs\node_modules\request\request.js:406:10) at new Request (c:\Users\Tien Nguyen\Desktop\profoundjs\node_modules\request\request.js:127:8) at request (c:\Users\Tien Nguyen\Desktop\profoundjs\node_modules\request\index.js:53:10) at Object.profound.sendRequest (c:\Users\Tien Nguyen\Desktop\profoundjs\profoundjs\api\sendRequest.js:88:3)



Convert low-code module to "real" PJS code to debug

If you want to debug that low-code module, you can go through the following steps to "convert" it into "real" PJS code and call it as an Express Route (web service). This is also a good way to learn how things are done behind the scenes. When a low-code module is called, the JSON file is "transformed" into "real" PJS code, and then that "transformed" module is run.

  • 1. On the PJS IDE, on code panel (upper center panel), in the top-left corner, click the </> button to "transform" the low-code steps into real PJS code.



  • 2. On the popup message below, click OK.



  • 3. VERY IMPORTANT! You can convert from low-code to real code only, not the other way! You can NOT go back! That is, you can NOT convert from real code back to low-code. So, after you see the real code show up on the next step, do NOT save the module file, if you want to keep it as low-code.

  • 4. The "real" PJS code is shown below:

  • 5. Copy/paste that code to somewhere (e.g. Notepad++) and save it.

  • 6. Close the file. Do NOT save it! If you save it, your module now will contain real code, not low-code anymore.

  • 7. Now, create a new web service with the code saved in step (5) above, with some minor adjustments, so that you can call it from a browser and debug it. As a general reference, click here to see how to create a web service. Follow the steps below to create a web service for this example.

  • 8. Click New/Javascript file.

  • 9. Enter the code below. This is pretty much the same as the code you saved in step (5) above, but changed so that it can be called as a web service from the browser, so you can debug it easily.

pjstips_04_2.js



10. Click Save As, and save as pjstips_04_2.js.

11. In the Files tree, right-click on newly-created file pjstips_04_2.js, and click Properties. Mark the file as an Express Route, using HTTP method of "GET", with the Route Path as shown below.



Now, put that PJS module into debug, and call it as a web service, with this URL: http://localhost:8081/run/pjstips/pjstips_04_2 .

You'll get the same error as before. But now, you can debug it, and find out where the problem is. Is it due to the way you answered the low-code questions?  Is it due to a bug in one of the PJS functions, even though you've answered all the low-code questions properly? In this example, if you step through the code in debug, you'll see that the error occurs on the call to PJS API pjs.sendRequest(). The problem here is that the "body" of the POST request is sent as JSON, but the "headers" says that the content type is ""application/x-www-form-urlencoded", so the API pjs.sendRequest() fails. To fix that, you can comment out the "headers" in this code, and test it to verify that it works here.

After the "headers" line is commented out in this code, the call to URL http://localhost:8081/run/pjstips/pjstips_04_2 works, and JSON object "data" is returned to the browser as shown below.

Now that you know that in PJS real code, the culprit is the incorrect "headers", you can go back to the low-code module, remove that in the plugin "Consume REST service"; use the RPG program to call the modified low-code module, and it should work OK.