Forums >> Programming >> Open Source >>
Updating My First Express App to Do Something




Posted:
bvstone

Updating My First Express App to Do Something

 
Updating My First Express App to Do Something

So, we've installed node.js.  We've installed Express.  We've created the skeleton for our first application.  Now, let's make it actually do something by using not only the database retrieval methods from the first sample (provided by IBM) but to also use Express and Jade to display some data.

What is Jade?

You probably caught the reference to Jade in the last sentence.  Remember when I said that node.js application development is like an onion, only in reverse?  Jade is just another layer that we need to worry about.

Jade is a template engine used to make creating your web pages more simple and less verbose.  Similar to how templates are used in the eRPG SDK and CGIDEV2, Express uses Jade by default as it's template engine.  

Now, Jade is also more complex and "alive" than templates used in RPG packages.  RPG templates used are simply text with placeholders to put data.  Jade's templates also have some structure and have the ability to use things such as loops and conditional statements.  While this is great, you now get to decide if you want your logic to be in your node application and/or your Jade template.  Again, the layers just keep getting more complex (however neat they are).

The List Printers Application

Let's get back to our application used to list printers we have available through Google Cloud Print.  This data is stored in a file on our IBM i in our G4G library named G4GPRTPF.  The file layout looks like the following:

 3/27/16             List File Field Description (LSTFFD)   
13:25:45                                                    
                                                            
File Name . . . . G4GPRTPF                                  
  Library . . . .   G4GBVS                                  
Format Descr  . .                                           
Format Name . . . RG4GPRT                                   
File Type . . . . PF            Unique Keys - N             
                                                            
Field Name FMT Start Lngth Dec Key Field Description        
GGPID       A      1   256         Google ID                
GGPPRTKEY   A    257    64         Printer Key              
GGPPRTID    A    321    64         Printer ID               
GGPSTATUS   A    385    64         Status                   
GGPNAME     A    449   256         Name  

For this application we will worry about the ID (GGPID) and the Printer Name (GGPNAME).

First we need to create a route.  That means, when someone goes to our site with the listPrinters path, we want that specific application to be run.  This most likely can be done with dynamic routing (as it is in Apache) but at this point, we haven't gotten to that yet so first we will update the app.js application inside the listPrinters directory that was created when we created our application skeleton.

...
var routes = require('./routes/index');
var users = require('./routes/users');
var listPrinters = require('./routes/listPrinters');

...

app.use('/', routes);
app.use('/users', users);
app.use('/listPrinters', listPrinters);

The above shows the modified code.  The two lines we added were:

var listPrinters = require('./routes/listPrinters');

and

app.use('/listPrinters', listPrinters);

This says when a user visits http://oursite.com/listPrinters to fire off the node module named listPrinters.js which should be located in the ../listPrinters/routes directory.  (You should also see the other two modules named index.js and users.js as well in this directory).

The node module code for listPrinters.js is as follows:

var express = require('express');
var db = require('/QOpenSys/QIBM/ProdData/Node/os400/db2i/lib/db2');
var router = express.Router();

var DBname = "*LOCAL";

/* GET home page. */
router.get('/', function(req, res, next) {

	var sql = 'select GGPID, GGPNAME from g4gbvs.g4gprtpf';
	console.log("SQL statement : " + sql);
	db.init();
	db.conn(DBname);
	db.exec(sql, function(rs) {
		console.log(rs.length);
		res.render('listPrinters', { title: 'List Printers', printerList: rs});
	});
	db.close();
	
});

module.exports = router;

This looks pretty simple, doesn't it!  Well, it sort of is.  

First we require express module, since we're running this node application in the express framework.

Next we require the database module that is specific to the IBM i.  This allows us to access IBM i DB2 data using SQL statements.

Next we run a simple SQL statement and render the result set using the render() function.  Now, this is where Jade comes in.  The render() function is in the documentation.

The first parameter is the name of the template to load, and following that we list variable names and data that we want to replace in the template.

In our example you'll notice we're replacing two things:

  • title - The title of the page
  • printerList - The list of printers we received tin the result set of our SQL statement.

Yes, we choose to pass an entire list into our template as a whole.  The other option would be to loop through the result set and try to render each item list 1 by 1.  But with the Jade template engine we can move that processing to the template.

So lets take a look at this template we keep hearing so much about:

extends layout

block content
	html
	head
		style
			table, th, td {
			border: 1px solid black;}
		h1= title
		
	body
		table
			tr
				th ID
				th Printer Name
			each printer in printerList
				tr
					td= printer.GGPID 
					td= printer.GGPNAME  


Yep, that's it.  Pretty simple, but then again so is our application.  

As you can probably tell, each of the HTML DOM items are created using keywords.  Those keywords are normally the same as the HTML tag, just without the <> brackets around them (ie, html produces <html>, body produces <body>, etc).

The indentation also plays an important role.  Everything indented after a specific keyword will be included inside of that specific container.  It is also important to note that indentation can be done with TABs or spaces, but NOT both.  I haven't decided which is best yet, though.  So for now I'm using tabs.

We then get to the table portion of our application that is used to list the printers.  And that part coincides with the render() function from our node application:

res.render('listPrinters', { title: 'List Printers', printerList: rs});  table
   tr
     th ID
     th Printer Name
     each printer in printerList
       tr
         td= printer.GGPID 
         td= printer.GGPNAME 

Remember in our node application where we passed the result set (rs) to a variable in our template named printerList?  Well, where's where see see how this takes place.

Notice the line:

each printer in printerList​

What this does is tell template to take the list of printers (printerList) and for each item in it, loop through and output a table row (each containing two table cells, one for the ID and one for the Printer Name).

It's actually pretty slick, especially since we can pass the result set directly to the template instead of having to convert it to a string, or convert it from JSON to XML, etc.  The less massaging we have to do the better.

So What Does the End Result Look Like?

Well, I thought you'd never ask.  After using navigating in PASE (or your favorite SSH terminal) to the ./listPrinters directory we issue the command:

npm start

or, if you wish to turn on debugging for the job, you can use this command:

DEBUG=listPrinters:* npm start

We then tell our browser to visit http://yourserver/listPrinters and are greeted with the following results (assuming everything works ok):

List Printers

ID Printer Name
bvstone@gmail.com Dell 2135cn MFP PCL6
bvstone@gmail.com Save to Google Docs
bvstone@gmail.com Fax (redirected 1)
bvstone@gmail.com Microsoft XPS Document Writer (redirected 1)
bvstone@gmail.com ABS PDF Driver v400 (redirected 1)
bvstone@gmail.com PrimoPDF (redirected 1)
bvstone@gmail.com Dell 2135cn MFP PCL6 (redirected 1)
bvstone@bvstools.com Save to Google Drive
bvstone@bvstools.com Dell 2135cn MFP PCL6
bvstone@bvstools.com HPCE924F (HP ENVY 7640 series)

Pretty slick, huh?  Yes it is.  But, I have a feeling as we move on there will be much more complexity that until we are comfortable with it may be a bit confusing.  Also, we don't know all the neat little tricks and features available to us yet either (for example, I have always designed my websites using Server Side Includes...I hope this is a possibility as it really helps create a web page built from smaller pieces).

You see, as a web application programmer that traditionally used RPG, I only had a couple things to worry about.  

  • My RPG programs
  • My Templates

Pretty straightforward.  Pretty easy.  The Apache config did all the "routing" with one simple command (well, two if you count the redirect directive and the container that allowed access to the RPG program in question).

With this node.js example using express we are starting to see the layers of complexity add up.  And at first it may be overwhelming, but I'm hoping in the end that is only because of the unfamiliarity with it.                           

                              


Last edited 03/29/2016 at 14:12:28


Reply




Copyright 1983-2017 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).