Node.js ist eine serverseitige Laufzeitumgebung, um Webanwendungen oder Webservices zu erstellen. Für das Erstellen von interaktiven Webseiten wird clientseitig JavaScript verwendet. Hieraus entstand die Idee, JavaScript auch für Serveranwendungen zu nutzen. Die Laufzeitumgebung ist die V8 Engine von Google, das bedeutet, dass auf der IBM i die gleiche JavaScript Engine wie im Google Chrome Browser implementiert ist. Node.js ist seit Dezember 2014 für die IBM i kostenlos verfügbar.
Ehe sich Node.js verwenden lässt, sind die Systemvoraussetzungen und die Installation anzusprechen. Ein Einstieg in diese Technik findet sich im Web unter
https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/IBM%20i%20Technology%20Updates/page/Node.js
Um Node.js zu installieren, benötigen sie mindestens V7R1 und folgende Lizenzprogramme:

5770-SS1 Option 33 Portable App Solutions Environment
5733-SC1 Option 1 OpenSSH, OpenSSL, zlib
5770-DG1 *Base IBM HTTP-Server für i
5733-OPS Option 1 Node.js Runtime

Bei Node.js handelt es sich um ein kostenfreies Lizenzprogramm, das derzeit in drei Versionen auf der IBM i verfügbar ist:

5733-OPS Option 1 Node.js V0.x
5733-OPS Option 5 Node.js V4.x
5733-OPS Option 10 Node.js V6.x

Nach der Installation befindet sich Node.js in folgenden Verzeichnissen:

V0.x /QopenSys/QIBM/ProdData/Node
V4.x /QopenSys/QIBM/ProdData/OPS/Node4
V6.x /QopenSys/QIBM/ProdData/OPS/Node6

Wenn Sie Node V4 oder V6 nutzen wollen, dann stellen Sie die Version über die Qshell ein:

V4: 5250> qsh
$ /QOpenSys/QIBM/ProdData/OPS/Node4/bin/nodever.sh 4
Node.js v4 will now be used.
V6: 5250> qsh
$ /QOpenSys/QIBM/ProdData/OPS/Node6/bin/nodever.sh 6
Node.js v6 will now be used.

Jetzt können Sie prüfen, welche Version von Node.js und dem Node Package Manager eingestellt ist. Der Node Package Manager ist ein Dienstprogramm, um Open Source Software (derzeit 240.000 Pakete) zu installieren, zu aktualisieren und zu löschen (www.npmjs.com).

5250> qsh
$ node -v
v6.9.1
$ npm -v
3.10.8

Erste Schritte mit Node.js

Wenn Sie es bis hierher geschafft haben, dann sind Sie bereit für Ihr erstes JavaScript Statement unter Node.js

5250> qsh
node
console.log('hello world')

Der nächste Schritt ist, diesen Befehl in einem Skript zu hinterlegen und das Skript aufzurufen:

  1. Legen Sie unter dem Verzeichnis /home das Verzeichnis Node an.
  2. Erstellen Sie eine Datei mit dem Namen helloworld.js.
  3. Öffnen Sie die Datei mit einem Editor, zum Beispiel RDI, Notepad++ oder dem Editor Ihrer Wahl und fügen Sie die Zeile console.log(‚hello world‘) ein. Speichern Sie die Datei.
  4. Starten Sie die Qshell mit qsh.
  5. Starten Sie das helloworld-Skript mit node /home/node/helloworld.js.

Einen Webservice mit Node.js programmieren, der „hello world“ im Browser ausgibt

Als Nächstes erstellen wir einen HTTP-Server und geben unser „hello world“ im Browser aus. Dafür erstellen Sie eine Datei mit dem Namen myserver.js im Verzeichnis /home/node mit folgendem Inhalt:

var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('hello world');
res.end();
}).listen(8020);
console.log('Server auf Port 8020 gestartet');

Falls bei Ihnen der Port 8020 belegt ist, dann prüfen Sie mit NETSTAT *CNN, welcher Port frei ist.
Danach starten Sie das Programm in der Qshell:

5250> qsh
node /home/node/myserver.js
Server auf Port 8020 gestartet

Jetzt öffnen Sie einen Browser Ihrer Wahl und geben in der URL die IP-Adresse Ihrer IBM i und folgenden Port ein: http://IhreIP:8020. Dann erscheint „hello world“ im Browser.

Einen Webservice mit Node.js programmieren, der Daten aus der Datenbank liest und im Browser ausgibt

Dieser Webservice liest Daten aus der Datei QIWS/QCUSTCDT, die mit A beginnen, und gibt sie im Browser aus.
http://IhreIP:8080/MyWebservice?name=A%25
Der Webservice wird mit dem Parameter name=A% aufgerufen. Dieser Parameter wird an das Programm übergeben. Im Programm wird daraus das SQL-Statement:

SELECT CUSNUM, trim(LSTNAM) as lstnam, trim(CITY) as City, BALDUE
FROM QCUSTCDT
where lstnam like A%;

Die Daten nach dem Fragezeichen heißen Query-String. Der Query-String darf nur Zeichen, Ziffern und bestimmte Sonderzeichen enthalten. Alles andere muss URL-Encoded werden. In unserem Beispiel wird das %-Zeichen zu %25 URL-Encoded.
Einen Online-Encoder und -Decoder finden Sie hier:
http://meyerweb.com/eric/tools/dencoder/
Auf der IBM i funktioniert das URL-Encoding sehr gut mit SQL:

values(systools.urlencode('Test Encoding mit den Umlauten äöü ÄÖÜ','UTF-8'));

ergibt folgenden String:

Test+Encoding+mit+den+Umlauten+%C3%A4%C3%B6%C3%BC+%C3%84%C3%96%C3%9C

Der obige Aufruf des Webservice bringt Daten in JSON-Notation:

{
"success":true,
"errmsg":"",
"records":2,
"items":[
{
"CUSNUM":"846283",
"LSTNAM":"Alison",
"CITY":"Isle",
"BALDUE":"10.00"
},
{
"CUSNUM":"583990",
"LSTNAM":"Abraham",
"CITY":"Isle",
"BALDUE":"500.00"
}
]
}

Für das Programm erstellen Sie eine Datei im Verzeichnis /home/node mit dem Namen webservice.js und kopieren folgenden Programmcode hinein:

5250> qsh
node /home/node/webservice.js

Anschließend starten Sie das Programm in der Qshell.

var http = require('http');
var url = require('url');
var querystring = require('querystring');
var db = require('/QOpenSys/QIBM/ProdData/OPS/Node4/os400/db2i/lib/db2');
var util = require('util');
var responseData = {
success: '',
errmsg: '',
records: '',
items: ''
};
http.createServer(function (request, response) {
var start = timerStart();
var pathname = url.parse(request.url).pathname;
var values = querystring.parse(url.parse(request.url).query);
console.log('Pathname: ' + pathname);
console.log('Querystring: ' + url.parse(request.url).query);
console.log('Values:' + JSON.stringify(values));
response.writeHead(200, {'Content-Type': 'application/json'});
response.end(readCustomers(values.name));
console.log('Runtime: ' + timerEnd(start));
}).listen(8080);
function readCustomers(value) {
var select = 'SELECT CUSNUM, trim(LSTNAM) as lstnam, trim(CITY) as City, BALDUE FROM QCUSTCDT';
var where = util.format("where lstnam like '%s'", value);
var sql = select + ' ' + where;
var data = '';
console.log("Sql: " + sql);
db.init();
db.conn("*LOCAL");
db.exec("SET SCHEMA QIWS");
db.exec(sql, function(rows) {
data = createResponse(rows);
});
db.close;
return data;
}
function createResponse(rows) {
if (rows.length > 0) {
responseData.success = true;
responseData.errmsg = '';
responseData.records = rows.length;
responseData.items = rows;
} else {
responseData.success = false;
responseData.errmsg = 'No records found';
responseData.records = rows.length;
responseData.items = '';
}
return JSON.stringify(responseData);
}
function timerStart() {
return (new Date()).getTime();
}
function timerEnd(start) {
return ((new Date()).getTime() - start) + "ms";
}

Dieses Projekt finden Sie unter https://github.com/RainerRoss/webservice-IBM-i-and-Node.js.
Viel Spaß beim Ausprobieren.