Archive

Archive for December, 2011

Pete's Wordshop › Mobile application development and IBM i (Part three) – To the web!

December 31st, 2011 Comments off

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!

 


Read the original at Pete's Wordshop.

Categories: Blogs Tags:

midrange.com - In My Humble Opinion › Al Barsa Challenge 2011 – Follow up

December 16th, 2011 Comments off
I’m pleased to announce that we met all the goals set for the 2011 Al Barsa Challenge! We received $2330 in contributions and had $4050 in matching donations for a total of $6380. Thanks to … Amanda Shaw, Leo Whitakar, Laura Ubelhor, Jon Anglis, David Willenborg, John Voris, Sharon Bodine, Guy Vig, Jenniefer Halverson, Marty [...]



Read the original at midrange.com - In My Humble Opinion.

RPG and Programming › The Human Factor

December 3rd, 2011 Comments off

Still another example of the human factor being one of the greatest hindrances in solving computer problems - the willingness to see what one expects to see and to make assumptions.

I was writing a report that required me to accumulate data into arrays in the program, which, associated together in a data structure, could then be sorted appropriately with a SORTA statement. Below this, I had defined a separate, somewhat unrelated data structure.

In the array data structure, properly defined by the way, was an account number, followed by a short name. When I printed the report, to my surprise I found the account number slopping over into the short name and practically missing in the account number field

I have WDSC, the PC program that color codes fields and opcodes and creates outlines of the code, including a cross-reference of the fields in the program. The cross references indicated only one spot where the account number and name fields would be updated. The update was airtight, as far as I could see, when I ran the program in debug. But at the point just before the second element of the arrays were to be updated, the first elements of the arrays were already changed!

I then looked a little more carefully at the “watch” facility of the debugger, which allows you to tell the debugger to tell you when the value of a specific field changes. After the first element of the array was filled, I told it to watch for when the first element of the account number changed. I then told the program to continue. Then the cursor stopped- at my input file definition!

“Now, what’s going on?” I said to myself. The file was externally defined, but one field from the file was used in the data structure below the data structure defining the arrays. I looked at that data structure, and everything seemed to be in order. I checked other things, and I came back to that data structure and puzzled over it. And then I saw. The line (with the DS in it) that forms the initial definition of the description had an asterisk in column 7 - for some reason along the way, I had commented the line out and neglected to remove the asterisk when I was done.

With that asterisk in the definition line, its data structure fields that followed became associated with the array data structure above. The field thus overlaid the first 11 bytes of the data structure array, which included the account number and name. The field was read in, and the arrays changed.

Even with the color coding of the editor, I completely missed the asterisk. I had seen what I expected to see - the DS in the appropriate column. I missed the asterisk. Now, one could say that this is an argument for using the // freeform notation for comments and devising a new, freeform, keyword style form for field and data structure definition. But there is more to it.

I would submit that, no matter what precautions we take, the human factor will come into play. At some point, no matter what notation we use, the problem being handled will become sufficiently complex that the human writing the program will start making assumptions so he can handle the volume of concepts and data coming in, and he will see the concepts in his program that he expects to see- even if they are not there.

Sometimes it’s best just to take a break.


Read the original at RPG and Programming.

Categories: Blogs Tags: , , ,