26
Thu, Dec
0 New Articles

Node.js on IBM i: Vexing Versions

Programming - Other
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

We have been writing and using functions all along without much commentary, so it’s time to back up and deal with them. Check out Part One of this excerpt series.  And Part Two and Part Three here.

Editor's Note: This article is excerpted from chapter 10 of Open Source Starter Guide for IBM i Developers, by Pete Helgren.

Node.js is a server that is written in JavaScript with the V8 engine at its core, running modules that are, by and large, written in JavaScript. So a good grounding in JavaScript is necessary to wrap your head around the code. The really good news here is that there is much, much of the heavy lifting done for you because there is a plethora of modules that will do already what you want to do. So, we’ll be leveraging a lot of the available modules in our examples because writing them from scratch would be a waste of time. We will spend some time talking about npm, the node package manager, and then we’ll look at examples of how to implement our brilliant ideas in Node.js.

The node package manager was a necessary first step because it was quickly realized, as it was with Ruby/Rails, that integrating functional components from other sources would be a highly efficient way to build applications. The great thing about open source is that the community is always learning from the past, taking the best practices, properties, and attributes of other languages and projects and integrating them into the current languages and projects. Thus, when it came to creating a package manager for Node.js as it rapidly grew, the developers leveraged the things like wget, gem, rpm, PEAR, CPAN, and a host of others, no doubt. The concept of getting a package from a remote repository and installing it isn’t new. How it is done is the key, and npm does it well.

There are a few caveats to using npm. Recently the interdependent nature of npm modules was exposed when a developer of a set of base modules, used practically everywhere, decided to yank his npm modules due to a dispute over naming conventions and trademark infringement. The removal of this module from the repository caused the other modules that depended on the module to not install (missing dependency!) and brought no end of woe to users of Node.js and npm for a few anxious days. The folks

at npm restored the missing modules, but the problem has led to some changes on how the modules are managed and how they can be removed from the repository. In addition, modules are given a cursory vetting for security issues, coding practices, or malicious intent—so, as always, caveat emptor, even if it is free.

npm is included with Node.js, so there isn’t anything you need to install to use it. You just run npm install <package name>. There are a couple of different ways that you can install packages. You can install them locally, as a folder off of your current project folder, or globally, so that the same package is available to all of your applications, regardless of where you located the project folder. There are many configuration options on how to override default locations and behavior, which we won’t deep dive into now. In most cases, you’ll install packages locally. There isn’t much of a downside. If you are like me, you’ll work on a project and get it working just fine and then want it to stay that way.

If you install locally, you can have a pretty good feeling that your app won’t get jacked up by you, or someone else, updating your packages to something incompatible. With a global install, you might end up shooting yourself in the foot by updating a global package you need for another project, thus breaking another project that is unrelated but uses that globally installed package. So, even though you might find yourself installing the same packages in several project folders, at least they can live independent of any other updates.

There is a way to save your bacon on your project dependencies: use a package.json file to list your project’s dependencies, so that you get the correct packages and versions you need. There are a boatload of options available for a package.json, and we aren’t going to explore them here. But this can give you an idea, at least, of what it would take:

20240214HelgrenCh10Fig1

This is a package.json file from a project I have at GitHub (https://github.com/phelgren/rpg-node). You can see how the project is defined. I gave it a name, version, and a clever description, and then I identified the versions of packages needed to run the code. The caret symbol (^) basically “locks down” the package version to the major/minor version stated. So in the example above, "body-parser" has to be at least version 1.11.0 but cannot go above a version 1.99.99. That is a way to keep from accommodating a version change that could have breaking changes. You can see the app also uses express and  socket.ioSo, package.json is a way to try to keep your projects stable in a very volatile, package-crazy world.

Yes, now we can take a look at some Node.js application building!

Just like any of the open source software we have looked at so far, Node.js can be installed on just about any platform. So if you are a Windows user, you can install there. If you are a Mac user, you can install there, and for you Linux folks, go ahead, make my day, and install it there. Node was originally part of the PowerRuby project (still is) but grew longer legs and is now a standalone product on IBM i. Python was originally needed as a scripting tool in order to install and compile other stuff, so we have a pretty robust, happy ecosystem in the IBM i world. I recommend that you install Node.js on whatever your “local” machine is because it is pretty convenient and is just drop-dead simple to deploy to IBM i whenever you need to “smoke test” an app in the IBM i world.

Installing Node.js is as “easy” as installing licensed program 5733OPS Option 1 on your IBM i. Easy as in “seems easy,” and, as I mentioned elsewhere, installing the IBM i OSS product is a little different than normal. The first install of the product is a bit of a head scratcher because even though you may want to install only Node.js, the most humane approach is to add all 15 options at the time you install 5733OPS—in the future, you will thank me, even if six of the 15 options are currently placeholders. It’s a good time to put on the latest PTFs as well, and it may take a bit of time because the IBM i OSS ecosystem is pretty diverse, and the prerequisite and co-requisite PTFs may hit quite a few other products.

Vexing Versions

The only thing you might run into as you move from one node environment to another is that the IBM i world isn’t quite as progressive as the run of the mill Node.js world, so the version on IBM i might be slightly older than what you would find “in the wild.” That is OK. Unless you are really pushing something to the bleeding edge, some version mismatching won’t kill you. Node changed the version system it was using in late 2015.

There was a “fork” of Node.js into a new project called io.js in January 2015, and the two, though similar, headed in slightly different directions. The pre-fork Node.js was hovering around version 0.11.15, which my head says, “Wow! Long way to go to V 1.0!” My IBM i is running 0.12.13, and the current Node.js release is version 4.5.0. Confused yet? The IBM i version was a Node version released in ... March 2016, so it ain’t all that old. What gives? Well, the fork of Node.js and Node.js itself “kissed and made up,” and they combined the fork (io.js) back into the Node.js version. So, Node.js, a combination of the “old” Node.js and io.js, version 4.5.0, was released in August 2016. My guess is my IBM i version will soon be at 4.5.0 or greater (as I download PTFs in the background).

My Windows version of Node is 4.4.7, which is plenty compatible with what I am running on IBM i, so I build on Windows, deploy on i. I use the Sublime Text text editor as well, and IT uses Node to run JavaScript from the command line, so all is well and nicely unified. No worries!

Code! Let’s take a look:

Node.js on IBM i: Vexing Versions - Figure 2

Our excellent JavaScript walk-through comes in handy here. First step in our Node script is to “require” http. The  http module is included in the Node install; all you need to do is require the module, which is sort of like an OO version of a /copy in RPG. Require loads the module into the httpsvr variable, which is an object. In fact, we immediately make use of the methods present in the httpsvr object by invoking the createServer method!

One line and voilà: we have an HTTP server!

createServer is passed an anonymous function, which has two parameters (objects), request and response. Then within that function, we invoke the writeHead on the response object, passing the value of 200 and yet another object, a name-value pair, {"Content-Type": "text/plain"}. Without doing a deep dive on the HTTP protocol, an http response header must contain a status and a content type in order to be valid, so that is what we are going to give it, at minimum, at this point.

Wait a second: why are we dealing with a “response” when we haven’t even sent anything to the server? Well, in this minimalist, scaled-down example, we are just going to have our server belch out some text as it starts up and receives anything on the listening port. What will we send? Ah, the requisite “Hello World” just to prove that it works. We follow that with a response.end method that basically flushes out the text. Notice the .listen(8888); at the end? That is an example of method “chaining” where multiple methods can be invoked on an object. In the case of the httpsvr object that we instantiated, it has many methods that could be invoked; we just took advantage of the chaining option.

We could have also done this, with the same results:

Node.js on IBM i: Vexing Versions - Figure 3

Some folks like the compactness of method chaining, and some like to indicate the invocation of each method explicitly.

If you were to save the script into a file called server.js, you could invoke it by typing node server.js at the command line (presuming the node binary is in your path), and ... nothing happens at the command line! That is because now the server you created is waiting for anything to hit that port. So head to your browser and type in localhost:8888, and magically, “Hello world” will appear. Drop ... dead ... simple.

The challenge, of course, is to move on to something a wee bit more involved. In my case, I already have something: the “chat” app I created a couple of years ago. Actually the “chat” app is to Node.js as the “blog” app is to Ruby/Rails. It is kind of the de facto standard of demo apps. So let’s take a look at chat because it really does point out some of the features and concepts you would encounter in a more real-world setting. We’ll start with the simple “Hello World,” but you’ll notice that it is slightly different from the “plain” node app:

Node.js on IBM i: Vexing Versions - Figure 4

The obvious difference is the use of 'express'. Unlike http, express is not included with the base Node.js modules, so you’ll need to use npm to install it. Again, I recommend that you do it locally to your project for now: npm install This email address is being protected from spambots. You need JavaScript enabled to view it..2. (I chose this version because I knew it worked.)

What express brings to the party is a bit more of a “framework” feel to the app. express is a Web framework, so we can use the methods it exposes to build our app. Could we have used a different framework? Sure! But express will meet our needs for this example. Let’s get grounded in the example:

Node.js on IBM i: Vexing Versions - Figure 5

We are requiring express, and see that little () at the end? That is the weird self-invoking function, which in this case initializes the app variable. That second line is very familiar because we saw it in our “Hello World” Node.js demo script. In that case, we passed an anonymous function to the http module. In this case, we pass it the function handler Server(app), which will process the request and response parameters needed by the HTTP protocol. So far, so good. The next line is completely new:

Node.js on IBM i: Vexing Versions - Figure 6

This is actually a “route,” which basically says anything that is requested ('/') will get the following response sent back to the browser: “Hello IBM i Node world!” Later on, you will see the effects of routes more directly, but the route is part of a RESTful application. Finally, the last line:

Node.js on IBM i: Vexing Versions - Figure 7

just starts the app listening on port 3888 and also outputs 'listening on *:3888' to the console, so you know there is life there! So far, nothing radically different from our original “Hello world.” Let’s move on. We’ll need a little more infrastructure for this step. Since we are creating a Web application, we’ll need some HTML to frame and tart up the look and feel. Here is what we will use:

Node.js on IBM i: Vexing Versions - Figure 8

Node.js on IBM i: Vexing Versions - Figure 8 (cont.)

Most of you folks are not Web monkeys, so the bits here may not mean much to you. But the short story is that we have an unordered list with an ID of "messages", which is just a placeholder for the list we’ll be creating later. We have a form field with no action, and we have a single field for entering some value and a button.

I left out the CSS, but it will be used to decorate the HTML. I’ll put it in a separate file and reference it in the HTML. We make the following change from a res.send method, which outputs an HTML string, and instead replace it with sendFile and point to our index.html file, like this:

Node.js on IBM i: Vexing Versions - Figure 9

You can verify that it works by running localhost:3888 in your browser (or use the IP address of your IBM i; 10.0.10.205:3888 is the internal address for my i). So we have basically created a very fancy “Hello World” app so far. It really doesn’t do much, but it looks pretty good. A chat app typically connects and communicates over a socket because there can be multiple folks chatting at a time, so we’ll need some socket infrastructure in order to get the chat app built. Fortunately, there is a module for that: socket.io. npm install is our friend again here. Run this command:

Node.js on IBM i: Vexing Versions - Figure 10

Then we need to make a few modifications to our code. We’ll add a bit of code that basically will be a “smoke test” on our socket connection and will emit “a user connected” to the console whenever we have a new connection, just like we see “listening on *:3888” after the server starts. Like so:

Node.js on IBM i: Vexing Versions - Figure 11

We also need to tart up our HTML and add a JavaScript reference to implement the client side of the socket. Our io object on the server implements the server side. Include this before the closing </head> tag:

Node.js on IBM i: Vexing Versions - Figure 12

Now the server console will indicate when a user connects. We probably also want to have some indication when a user disconnects, so let’s monitor for that and output to the console when that event occurs.

Node.js on IBM i: Vexing Versions - Figure 13

Still nothing real special here. All we see is connect and disconnect events. Nothing the least bit chatty going on at all. So let’s add another incremental step. Let’s take what is submitted in our message input element and output that into the console (baby steps!). I have added a little more infrastructure as well. I added the jQuery JavaScript library to add some more terse methods to keep the code compact. So we now have a bit more JavaScript in the HTML and a bit more JavaScript code on the server:

Serverio.on('connection'.......... ):

Node.js on IBM i: Vexing Versions - Figure 14

HTML <script>:

Node.js on IBM i: Vexing Versions - Figure 15

Note: The $("#...") references are the same as using the document.getElementById("...") methods in the DOM.

So what we have is a chat demo that only chats out to the console. Let’s fix that!

The io.emit method is what we call when we want to send data out. If we don’t qualify who the “emit” is for, it goes to everyone. All it takes is one more line of code on the server:

Node.js on IBM i: Vexing Versions - Figure 16

HTML <script>:

Node.js on IBM i: Vexing Versions - Figure 17

Compare that to the similar socket.emit method. In the example we are using, we “target” the 'chat message' client and send the data contained in the message input element. In the io.emit method (on the server), we send the data to everyone who is connected, and on the 'socket.on' method (on the client), we capture what was sent and use jQuery’s append method to add it to the 'messages' (unordered) list element.

We have been walking through this piecemeal, so let’s take a look at the whole tamale. First the HTML:

Node.js on IBM i: Vexing Versions - Figure 18

Node.js on IBM i: Vexing Versions - Figure 18 (cont.)

Node.js on IBM i: Vexing Versions - Figure 18 (cont.)

And a wee bit more stuff that makes the HTML look a little better in the chat.css file:

Node.js on IBM i: Vexing Versions - Figure 19

I also did something tricky along the way that we haven’t talked about but is reflected in the code above. In the original version of this example, the CSS was included in the HTML. That is not an accepted practice except in the case that just a very few tweaks are needed. In this case, the CSS used is not extensive, but very often your CSS, JavaScript, and HTML reside in separate files so they can be individually maintained. So I put the CSS in a separate file, just as you would expect in a larger project. But that takes a bit of trickiness, as I said. You need to add the line:

Node.js on IBM i: Vexing Versions - Figure 20

So you can serve up your “static” files. Basically the code is saying that all of the static stuff will be found in the public folder, relative to the project folder you are running in. So the chat.css is living in there along with the jquery-3.1.0.js file. The <script src="/ socket.io/socket.io.js"></script> reference is something different, though. The socket. io.js file lives in the node_modules/socket.io/node_modules/socket.io-client folder, but the initialization of the module “exposes” the file as though it were off the root of socket. io. Thus, it doesn’t live in the 'public' folder like other non-module js files do.

Next time: Part 5 - System Access and DB2 Database Access.  Can't wait?  You can pick up Peter Helgren's book, Open Source Starter Guide for IBM i Developers at the MC Press Bookstore Today!

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: