Node.js on IBMi
The event-driven, non-blocking I/O model makes it lightweight and very efficient. It also provides several built-in modules to simplify programming, especially for networking applications. Additionally, there are more third-party modules that can be easily installed with the built-in npm (Node Packaged Modules) tool.
Node.js on IBMi
Node.js is now being delivered and packaged for IBM i with the new IBM i product 5733-OPS – Open Source for IBM i – Option 1. This new offering includes the following:
- Node.js runtime – Core Node.js runtime engine compiled to run in PASE on IBM i
- DB2 for i access library – Allows user to access content stored in DB2 for i.
- Node.js toolkit for IBM i – Allows user to access IBM i system resources, such as system status, system values, job information, message queue, object information, ILE Programs etc.Note: Node.js is a registered trademark of Joyent, Inc. in the United states and other countries. This module is not formally related to or endorsed by the official Joyent Node.js project.
To get going with Node.js on IBM i, use the following instructions
Software Prerequisites How to obtain the new Open Source for IBM i Product – 5733OPS Install & Setup Node.js on IBM i Verifying the Node.js Environment Running ‘Hello World’ in Node.js on IBM i DB2 Access from Node.JS Access IBM i Native Objects
DB2 for i access APIs Toolkit for IBM i APIs
It contains all the node.js PTF information.
Fun Times for RDi Users With v 9.5
RDI 9.5 Enhancements, Version 9.5 of Rational Developer for i is now available. It does require a re-install—not just an update. So what’s new in RDi V9.5?
RDI 9.5 Enhancements
The most significant new feature is the capability to format (or more accurately re-format) your free-form logic. What we’re talking about here is the matter of indentation of the code.Let’s say, for example, you have a FOR or DOx loop that has a SELECT/WHEN block nested inside it and an IF/ELSE block nested inside that. Now you need to add another level of nesting with another IF/ELSE block that falls between the FOR/DOx and the SELECT block.
One of the benefits of free-form logic is the capability to indent code to show the levels of nesting. This makes it easier for the next programmer coming along to follow the logic. Needless to say, this makes it critical that the indentation is accurate! Even if we make the bold assumption that the original code was indented properly to begin with (sadly in our experience, this is often not the case), introducing a new level in the middle requires shifting a bunch of code around to get the indentation to correctly reflect the nesting levels. There are various ways to do this manually, of course, but it was often not done properly or at best was time-consuming to do and tended to be somewhat error-prone. The new formatter only works on code that is already in free format—including file and data declarations, etc.
The built-in formatter for RDi V9.5 can be used on a specific block of code or, if no block is selected, the entire member is formatted.
The Crtl+Shift+F keyboard shortcut will invoke it or you can use menu options—either under the Source menu or via the right-click context menu under Source.You do have a few options on how the formatting is done. These are controlled via preferences on a new Formatter preference page under ILE RPG parser preferences.
There are options for how many spaces to indent and an option for whether or not you want WHEN/OTHER statements within a SELECT block indented. Take a look at the preference page to find a few others.
By creating simple display files and corresponding RPGLE programs to display we can call Python programs to provide users with features that are either very complex or impossible to implement with pure RPGLE.
At the moment I have been calling a CL program from the RPGLE program. I plan to update this to use the QCMDEXC API and negate the need for a CL program.
We check the users input then call the CL program which in turn calls the python script
In this excerpt we use the users logon name to lookup an email address in our users table
DDsUSer 254 263 DDUMPED S 1 * DRDATE S LIKE(SYNUMB) DLsOkay S N DMSGNO S 10 DMSGF S 10 DMSGDTA S 256 DFILDS3 DS 528 DFILDS4 DS 684 DFILDS5 DS 528 DPDATE S 5A DSECURE S 3 DSUSER S 10A DEMNAME S 35A DEMEMAIL S 100A ********************************************************************************************** * C EVAL *IN90 = *ON C DOW *IN03 = *OFF C WRITE MSGCTL C EXFMT SCREEN C* MoveA '00000' *In(30) C* MOVEA '00' *IN(42) C* MOVEA '000' *IN(42) C* MOVEA '0000' *IN(42) C* Eval *In46 = *Off C* EVAL #VALID = 'YES' C EXSR CLEAR C IF *IN03 = *OFF C * C IF *IN30 = *OFF * Get users email address C/EXEC SQL C+ Select EMEMAIL, EMNAME into :EMEMAIL, :EMNAME from USERTABLE C+ Where EMUSER = :DsUSer C+ Fetch first row only C/End-exec C* C If SQLSTT = '00000' C* ENDIF C* MOVE DsUser SUSER C Call 'PROGEXCL' C Parm PDATE C Parm DsUSer C Parm EMEMAIL C* C Eval MSGNO = 'TRI0069' C Exsr WRTMSG C Clear SCREEN C* EVAL *IN30 = *ON C ENDIF C ENDIF C ENDIF C ENDDO C ENDIF C EVAL *INLR = *ON
IBM opening up System I with the addition of languages such as Python, Node.JS & Ruby is a major step forward and has helped us achieve some amazing results. Python has many library’s available that enable the programmer to perform complex operations with ease. It is also very easy to read Python code so it is always clear what’s going on, I don’t think we can say that with RPG code.
The best way of working with these new options is to create a subsystem for Openssh server (following the excellent IBM Redbook on Openssh Server it may be old but still relevant). QSH/PASE can be tedious.
Using Python we can extend native report programs to include formatted XLSX output.
Access to system services (programs,commands,database) is provided through the excellent XMLSERVICE library from Young i Professionals (http://yips.idevcloud.com/wiki/index.php/XMLService/XMLSERVICE)
""" Configure: Requires XMSLERVICE library installed, see following link installation http://yips.idevcloud.com/wiki/index.php/XMLService/XMLSERVICE Transports: 1) XMLSERVICE direct call (current job) from itoolkit.lib.ilibcall import * itransport = iLibCall() 2) XMLSERVICE db2 call (QSQSRVR job) from itoolkit.db2.idb2call import * itransport = iDB2Call(config.user,config.password) -- or -- conn = ibm_db.connect(database, user, password) itransport = iDB2Call(conn) 3) XMLSERVICE http/rest/web call (Apache job) from itoolkit.rest.irestcall import * itransport = iRestCall(url, user, password) """ from itoolkit.lib.ilibcall import * itransport = iLibCall() from itoolkit import * sQry = 'QUERY' itool = iToolKit() itool.add(iSqlQuery('custquery', sQry)) itool.add(iSqlFetch('custfetch')) itool.add(iSqlFree('custfree')) # xmlservice itool.call(config.itransport) QCUSTCDT = itool.dict_out('custfetch') if 'error' in QCUSTCDT: print (QCUSTCDT['error']) exit() else: # Loop record set