Mobile application development and IBM i (Part three) – To the web!

So a lengthy delay in getting to the “webby” part of this post due to the holiday distractions.  This new post should, however, get you going again and get the creative juices going.

When last we met I walked through the “green screen” version of the “timeclock” app.  This would actually make a fairly poor mobile application unless you have a 5250 client for your mobile phone (such things do exists!).  But when it comes to mobile applications, either a native application or a web application is the way to go so we’ll start down the initial path of a web application which will eventually end up as a mobile native application.

We are still keeping it simple so you can get the basics under your belt.  So, a quick review.  The basic “cycle” of our RPG application (which doesn’t use ‘the cycle’) is this:

  1. When we enter the program we set some ‘global’ variables that we will use in the program.  Some of them are just initial variables like the ‘punchdate’, ‘punchtime’, the day of the week and initial indicators.  We also call a procedure to get the last punch of the employee (which is always employee ’55’).
  2. We then enter a loop that set’s a couple of indicators and then displays the 5250 screen (EXFMT) and then the program waits for a key event to continue processing. The code below the EXFMT is executed when the button for “Punch IN”, ‘Punch OUT” or exit is clicked (or alternatively when F6,F7 0r F3 are pressed).
  3. The procedure “Punch” does the heavily lifting.  All of this should be easily (!) discernible from the code if I have done my programming job right.

Again the reason for the sub procedures, which we could have coded more procedurally, is so that we could reuse them when we convert the 5250 program into a CGI web program with CGIDEV2. In our 5250 program we have 25 lines of operable code.  In our CGIDEV2 equivalent web program we have 26 lines, so our coding remains pretty much the same. The big difference? Note the missing DOU loop?  How can this work?  In our 5250 app the program loads and remains running until the exit key is pressed.  In our CGIDEV2 program, the web server calls and executes our RPG program but the program does not continue to run.  It is simply called again if the page is requested again. Web programming is essentially stateless.  It doesn’t retain a “context” between calls.  A user in China could access the page and another user in the states could access the page and the program is really clueless about the two locations.  As HTTP server technologies grew and pages became interactive then state was built into the process using a host of approaches, most commonly using and storing session information to track the users connection to the server.  5250 doesn’t suffer from this design so preserving state isn’t an issue in a 5250 program but it is an issue in Web development and although we won’t jump into the approaches it explains the unusual design of our CGI program.  It runs, it’s done.

So looking at the differences in the code. Let’s start with the “screen design” which in this case is bare bones HTML (well *almost* bare bones).  Lets start with the most important components (look at BASIC.HTML in source file HOSTHTML).  Take time to check out the w3schools.com website to understand the basic HTML directives if you are unfamiliar with them.  I don’t plan to dwell deeply on the HTML:

  • /$thepage – this directive gives a name to the section the CGIDEV2 will read and write to the HTTP server.  This is PURELY a CGIDEV2 directive.  PHP, the FreeMarker and Velocity frameworks and a host of other templating frameworks use different conventions for their directives but in this case CGIDEV2 uses this to denote the start of a ‘section’.
  • /%lastPunch%/, /%punchDate%/,/%doweek%/,/%punchTime%/  – These are all ‘placeholders’ in the HTML that will be replaced with data when the form is processed by the RPG CGIDEV2 program. Think of them as the field definitions in your DSPF.  The replacement is handled very automagically for you in 5250 programming.  In CGIDEV2 you need to be a bit more explicit.
  • The rest of the form has standard HTML.  You’ll notice a “hidden” field in the form called PB2.  We’ll use that to store which button was pushed, much like we did in the 5250 program (for comparison sake). We are writing out a table in the HTML using the <table> tags along with <tr> (table row) and <td> (table division – think column).  We draw a couple of buttons with the <input type=button> tags and we call some javascript (within the <script> tags near the top of the HTML) to process the button click events.

Examining the RPG (CGIDEV2) code (CGI_PUNCH.SQLRPGLE).  We have added some infrastructure for CGIDEV2 (all of the copy statements) and you’ll need all of them particularly don’t forget the prolog3 copybook (don’t ask me why I mention it….).  Outside the inclusion of some additional variables and copybooks, it looks pretty similar to our original.  With the following changes:

  • PunchBtn = %trim(zhbgetvar(‘PB2’)); – Remember that hidden text field? It is updated by the javascript on our HTML form but then read here in the program using the CGIDEV2 procedure zhbgetvar which basically pulls it from the HTML that was read in.
  • gethtml(‘HOSTSHTML’:’MOBILEREM’:’BASIC’); – Grabs the HTML for our page so we can write new data to it before it is sent back to the browser.
  • getLastPunch(employee); We run this procedure here because the “punch” procedures above could have just recorded a punch so we want to retrieve those values before we write them back to the page.
  • updhtmlvar(‘lastPunch’:lastPunch); All of the updhtmlvar calls write the data to the retrieved HTML page into the replacement fields we have identified.  The /%lastPunch%/ directive in the HTML will be replaced with the data in the lastPunch variable found in our RPG.  There is no need to name these the same.  The value on the left (‘lastPunch’) is replaced by the contents on the right (host variable :lastPunch) simple as that. Note that we ALSO update the hidden field PB2 with a ‘0’ so that our ‘button state’ is reset.
  • wrtsection(‘thepage’); Actually in this first iteration we have only one “section” which is the whole page.  wrtsection writes data to the server.
  • exit – just a cleanup routine that tells the server than we are done writing data.  It is flushed out to the browser at this point.

So that is basically it.  A web based app which *could* be called from a mobile device browser if you wanted to. It is pretty lightweight so it should be fairly performant.  In the first post on this subject, I talked about being a good citizen when it comes to data transfer – move as little data as possible.  We can improve this data movement and we will explore those options when we make this app much more mobile friendly.

What does this look like.  Well, like our 5250 app, it ain’t much to look at:

 

 

 

 

 

 

 

 

 

 

 

Missing is the “Exit” button.  Simply close the browser window to exit!  You’ll notice I added a small feature improvement in the web version of our timeclock you can now list the punches that have been recorded.  Not much of a feature improvement but, one step at a time!  Here is what that page looks like:

 

You can check out the code which you can download from here: The code is compiled for V6R1 (IBM i 6.1).  I’ll try to get it recompiled *PRV so it will be happy about a download for V5RM0.

The next step is to use HTML5 to dress up the web pages, add a little JSON and Ajax and make this a bit more mobile friendly!  Coming soon!  Happy New Year!

 

This entry was posted in Uncategorized. Bookmark the permalink.