Offshore node.js-development- Hire node.js Developers- Outsource Node.JS Development India
Node.js, DB2, RPG talking at last - · PDF file•Staff training on open source...
Transcript of Node.js, DB2, RPG talking at last - · PDF file•Staff training on open source...
Node.js, DB2, RPG
talking at last
Copyright 2015 Aaron Bartell
Aaron BartellDirector of IBM i Innovation
Credit Cards
• CyberSource Toolkit for i (more info)
• 100% RPG API toolkit that facilitates credit card processing through CyberSource
• Leverage payment tokenization to avoid storing sensitive data locally.
• Payment Terminal Toolkit for i (more info)
• 100% RPG API toolkit that facilitates credit card processing between EMV terminals and IBM I applications
• Supports EMV chip card transactions, standard swipe transactions, NFC payments, signature capture, and other existing terminal features.
IBM i Hosting (more info)
• Simple & cost effective
• Starting at $157 per month
Open Source Consulting (more info)
• Jumpstart Ruby on Rails or Node.js project
• Mobile app development
• Integrating existing RPG logic with modern UI
• Staff training on open source technologies.
RPG, XML, & Web Services (more info)
• Product: RPG-XML Suite
• Toolset to compose, transmit, & parse JSON or XML.
• Completely within the RPG environment. No Java.
UPS Shipping Integration (more info)
• UPS Toolkit for i; an RPG centric solution for IBM i businesses to communicate with UPS in real time.
What we do at Krengeltech...
Agenda
- Why should I care about Node.js?
- DB2 Access for i
- Toolkit for i (aka iToolkit)
What is Node.js? Make me care.
Server-side Javascript, uses Google's V8
Biggest benefit: One language for both client (browser) and server (IBM i). BIG TIME SAVER!!
Ported and supported by IBM. Home: http://bit.ly/nodejs_ibmi
Non-blocking I/O. Not unique to Node.js, though they made it popular.
w3schools.com/js - Javascript, getting starteddevelopers.google.com/v8 - Google V8en.wikipedia.org/wiki/MIT_License - MIT license
License
Talking to IBM i
DB2 Access for i● Descr: API set for manipulating DB2 for i from Node.js● Docs: http://bit.ly/nodejs_db2foriaccess● IFS Location: /QOpenSys/QIBM/ProdData/OPS/Node6/os400/db2i/lib/db2
Toolkit for i● Descr: API set for interfacing with XMLSERVICE.● Docs: http://bit.ly/nodejs_toolkitfori ● IFS Location: /QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit
bit.ly/nodejs_ibmi - IBM i Node.js Home
Config IBM i Environment
Do yourself a favor and DON'T use CALL QP2TERM, use SSH client instead.
Run the following in a PASE shell:
$ export PATH=/QOpenSys/QIBM/ProdData/OPS/Node6/bin:$PATH$ export LIBPATH=/QOpenSys/QIBM/ProdData/OPS/Node6/bin:$LIBPATH
Now you can invoke node binary from anywhere in the IFS.
$ node -vv6.9.1
Put the above exports into node_env.sh and then easily invoke it (note the period!)
$ . node_env.sh
bitbucket.org/litmis/nodejs/wiki/environment - IBM i Node.js Environment configbit.ly/chrome_ssh - Secure Shell in Chrome (browser)
What are YiPs?
YoungiProfessionals.com - Home sitelinkd.in/1iG3oIV - LinkedIn YiPs group
● Began as a group within COMMON USA as a way for young people to find each other at the COMMON USA annual conference.
● Goals: educate, advocate, and get involved!● IBM uses YiPs to share open source that originates from within
their walls (i.e. xmlservice, Ruby gems, PHP code, many tutorials on Git, PASE, ssh, FastCGI, etc)
● "Join" YiPs via LinkedIn YiPs group: linkd.in/1iG3oIV● Only need to be young at heart! :-)● YiPs open source repositories: bitbucket.org/litmis
YiPs = Young i Professionals
What is XMLSERVICE?
YoungiProfessionals.com/wiki/XMLSERVICE - Home siteYoungiProfessionals.com/wiki/index.php/NodeJs/NodeJs - Node.js on YiPs
Make use of all these from Node.js● DB2 for i – SQL and Native● *PGM call● *SRVPGM sub procedure call● Data Area● Data Queue● Message Queue● Commands● System values● Spool files
● Delivered with OS as of IBM i 7.1: TR5● Similar to IBM ToolBox for Java, but better in many ways● Great for re-use of existing RPG code from ANY language in your enterprise● Can be invoked via DB2 stored procedure or HTTP● Author: Tony Cairns, IBM Rochester● Source: bit.ly/bitbucket-xmlservice-rpg
… a single library of Open Source RPG code that enables XML scripting calls of IBM i resources using most any language available on your platform.
JSON version coming soon!
Flow and 10k foot view
XMLSERVICE
DB2PGMSRVPGMPASESystem APIUser SpaceWRKACTJOB
XML input from IBM i / Linux / Windows
Node.js, Ruby, PHP, Java, etc.
DB2 connection
REST GET/POST
XML
XML
<myscript> <pgm>...</pgm> <cmd>...</cmd> <sh>...</sh> <sql>...</sql></myscript>
itoolkit.js in action
● itoolkit.js is an XMLSERVICE wrapper.● Location:
/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit.js● Source repo: kti.news/litmis-nodejs-itoolkit
<?xml version='1.0'?><myscript> <cmd exec='rexx' error='fast'> <success>+++ success RTVJOBA USER(?)</success> <row> <data desc='USER'>QUSER</data> </row> </cmd></myscript>
Output --->
var xt = require("/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit");
var conn = new xt.iConn("*LOCAL");
conn.add(xt.iCmd('RTVJOBA USER(?)'));
conn.run(function(str) {
console.log(str);
});
node REPLType node at the command line to start a REPL session. Copy/paste code for quick testing! REPL = Read Eval Print Loop
nodejs.org/api/repl.html - REPL docs
xmlToJson
Javascript deals in JSON, not so much XML. . . enter xmlToJson API.
<?xml version='1.0'?><myscript> <cmd exec='rexx' error='fast'> <success>+++ success RTVJOBA USER(?)</success> <row> <data desc='USER'>QUSER</data> </row> </cmd></myscript>
Before After
conn.run(function(str) { result = xt.xmlToJson(str); console.log(result[0].data[0].value);});
[{ "type":"cmd", "success":true, "cmd":"RTVJOBA USER(?)", "data":[{ "name":"USER", "value":"QUSER" }]}]
debugging
============INPUT XML============<?xml version='1.0'?><myscript><cmd exec='rexx' error='fast'>RTVJOBA USER(?)</cmd></myscript>
var conn = new xt.iConn("*LOCAL");conn.debug(true);
Additional output:
Still can't determine why it's not working? It's open source! Look at the code. . .
/QOpenSys/QIBM/ProdData/Node/os400/xstoolkit/lib/itoolkit.js
Call a *PGM
The itoolkit.js and XMLSERVICE support much more complex program calls and even go beyond the PCML/Java Toolbox limitations.
NOTE: This is 100% free-form RPG, available in IBM i v7.1
dcl-pr pgm1 extpgm; char1 char(1); dec1 packed(7:4);end-pr;dcl-pi pgm1; char1 char(1); dec1 packed(7:4);end-pi;
char1 = 'C';dec1 = 321.1234;return;
MYLIB/PGM1
Invoke MYLIB/PGM1
var xt = require('/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit');var conn = new xt.iConn("*LOCAL"); var pgm = new xt.iPgm("PGM1", {"lib":"MYLIB"});pgm.addParam("","1A");pgm.addParam("0", "7p4"); conn.add(pgm.toXML()); conn.run(function (rsp) { var results = xt.xmlToJson(rsp); results.forEach(function(result, index){ result.data.forEach(function(data, index2){ console.log("type:" + data.type + " value:" + data.value); }); });});
encapsulation
var xt = require('/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit');var conn = new xt.iConn("*LOCAL"); function pgm1(char1, dec1){ var results; var pgm = new xt.iPgm("PGM1", {"lib":"MYLIB"}); pgm.addParam(char1,"1A"); pgm.addParam(dec1, "7p4"); conn.add(pgm.toXML()); conn.run(function (rsp) { results = xt.xmlToJson(rsp); }); return {char1: results[0].data[0].value, dec1: results[0].data[1].value};}exports.pgm1 = pgm1;
var rpg = require('rpg');var result = rpg.pgm1("A","0");result.char1;result.dec1;
sitepoint.com/understanding-module-exports-exports-node-js - Node.js export tutorial
rpg.js
Encapsulate RPG for easy invocation
data types (similar to RPG)
type='na' [varying='on|off|2|4'] - character (32A)<data type='32a'><![CDATA[<i am ranger>]]></data> type='npn' - packed decimal (12p2)<data type='12p2'>30.29</data> type='nsn' - zoned decimal (12s2)<data type='12s2'>30.29</data> type='nin' - signed integer (5i0, 10i0, 20i0)<data type='10i0'>-30</data> type='nun' - unsigned integer (5u0, 10u0, 20u0)<data type='10u0'>30</data> type='nfn' - floating point (4f2, 8f4)<data type='4f2'>30.34</data><data type='8f4'>30.34</data> type='nb' - binary HEX char (2b, 400b)<data type='5b'>F0F1F2CDEF</data><data type='2b'>1FBC</data><data type='2b'>0F0F</data>
youngiprofessionals.com/wiki/index.php/XMLService/XMLSERVICEQuick - Docs
http connection
● itoolkit.js supports DB2 or HTTP connection.● If 1-tier you don't need authentication with DB2 approach● iConn(string dataSource[, string user, string password[,object
options]])
Consideration: HTTP slower than DB2
var xt = require('/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/itoolkit');var option = { host : '192.168.0.10', port : 8000, path : '/cgi-bin/xmlcgi.pgm'};var conn2 = new xt.iConn('*LOCAL', 'USR1', 'bleh!', option);
Reality: Node.js can reside on Amazon/other and call into your IBM i with ease. But why not keep it on IBM i?
Stateful and Private● Used when IBM i resource will be called many times by the same user profile● Lasting persistent data needed by the IBM i resource (RPG vars, open files, etc.)
image courtesy of Tony Cairns
DB2 Access for i
[ { LSTNAM: 'Henning ', CITY: 'Dallas' }, { LSTNAM: 'Jones ', CITY: 'Clay ' }, { LSTNAM: 'Vine ', CITY: 'Broton' }, { LSTNAM: 'Johnson ', CITY: 'Helen ' }, { LSTNAM: 'Tyron ', CITY: 'Hector' }, { LSTNAM: 'Stevens ', CITY: 'Denver' } . . .]
Results
What: API set for DB2 database manipulation on IBM iLocation: /QOpenSys/QIBM/ProdData/OPS/Node6/os400/db2iModules: bin/db2ia.node and lib/db2a.jsDocs: bit.ly/dw-nodejs-db2-driver
Example
const db = require('/QOpenSys/QIBM/ProdData/OPS/Node6/os400/db2i/lib/db2a')const dbconn = new db.dbconn()dbconn.conn("*LOCAL")
const stmt = new db.dbstmt(dbconn) stmt.exec("SELECT LSTNAM,CITY FROM QIWS.QCUSTCDT", function(result,err) { console.log(result)})
Async driver
bit.ly/nodejs-ibmi-async - IBM docs
Original synchronous driver:
New asynchronous driver:
… use SQL bound parms.
const sql = "SELECT * FROM USERS WHERE ID=?"
bind = [
[id, db.SQL_PARAM_INPUT, 1]
]
db.execute_prepared(sql, bind, function (err, res) {
if (err) return callback(err, null)
return cb(err,res)
})
How do I prevent ?
wrapper'use strict'const db2a = require('/QOpenSys/QIBM/ProdData/OPS/Node6/os400/db2i/lib/db2a') var db = {} const dbconn = new db2a.dbconn()dbconn.conn("*LOCAL")dbconn.debug(true)const stmt = new db2a.dbstmt(dbconn)db.query = function (sql, cb) { stmt.exec(sql, function (result, err) { if (err) return cb(err, null) return cb(null, result) })} db.execute_prepared = function (sql, bind, cb) { stmt.prepare(sql, function(err){ stmt.bindParam(bind, function(err){ if(err) return cb(err) stmt.execute(function(x1, x2, x3, x4) { stmt.fetchAll(function(res, err){ cb(err,res) }) }) }) })}module.exports = db
model wrapperconst db = require('./db')
const schema = 'MYDB' || process.env.schema
const table = 'USERS'
let model = {
}
model.get = function(id, cb){
const sql = `SELECT * FROM ${schema}.USERS WHERE ID=?`
bind = [ [id, 1, 1] ]
db.execute_prepared(sql, bind, function (err, res) {
if (err) return callback(err, null);
return cb(err,res)
})
}
model.list = function(cb){
const sql = `SELECT * FROM ${schema}.USERS`
db.query(sql, function (err, res) {
if (err) return cb(err, null)
return cb(err,res)
})
}
module.exports = model
model wrapper usage
const user = require('./user'); user.get(1, function(err, res){ console.log(res);}); user.list(function(err, res){ console.log(res[0].EMAIL); console.log(res[1].EMAIL);})
metadata
Metadata is available on connection object via variety of functions: numRows, numFields, fieldName, fieldWidth, fieldType, fieldPrecise, fieldScale, fieldNullable.
bit.ly/nodejs_db2foriaccess - IBM docs
Metadata
stmt.exec('SELECT * FROM QIWS.QCUSTCDT', function(result, err) { var fieldNum = stmt.numFields(); console.log('Name | Length | Type | Precise | Scale | Null'); for(var i = 0; i < fieldNum; i++){ console.log('%s | %d | %d | %d | %d | %d', stmt.fieldName(i), stmt.fieldWidth(i), stmt.fieldType(i), stmt.fieldPrecise(i), stmt.fieldScale(i), stmt.fieldNullable(i)) }})
Future...
- Formal ORM support, Waterline is a popular option- Work has started: bit.ly/litmis-sails-db2fori Want to help?
github.com/balderdashy/waterline - Waterline repo/docs
User.create({ name: 'Walter Jr', age: 30 }).exec(function(err, user) {}); User.findOne({ id: 1 }, function(err, user) { // Do stuff here}); User.find().where({ id: { '>': 100 }}).where({ age: 21 }).limit(100).sort('name').exec(function(err, users) { // Do stuff here}); User.destroy({ id: 1 });
Home site: youngiprofessionals.com/wiki/index.php/XMLService youngiprofessionals.com/wiki/index.php/NodeJs/NodeJs bitbucket.org/litmis/nodejs
Articles and blogs: litmis.com/articles ibmsystemsmag.com/ibmi/developer/rpg/xmlservice_new_life/ ibmsystemsmag.blogs.com/idevelop/xmlservice/ iprodeveloper.com/blog/getting-your-data-xml-service iprodeveloper.com/development/unleash-your-ibm-i-xmlservice
IBM i Open Source Aggregation site: bit.ly/ibmioss
On the web
We Have Reached The End!
Now...Get Engaged!1. Visit litmis.com regularly for new content2. Follow @litmisteam on Twitter3. Contact me directly for assistance
jump-starting any open source development projects on IBM i at [email protected]