Reusing HTML and Form Filling with RPG CGI
September 1, 2004 Shannon O'Donnell
The code for this article is available for download.
In “Step by Step: RPG IV and Interactive Web Pages” I demonstrated how easy it is to use your RPG skills to push content out to a Web browser. The Web pages displayed in the article were built from within the RPG IV code. This article explains how you can reuse HTML documents in an RPG CGI program. You will also learn how to pre-load HTML form fields from RPG before displaying the document in the browser.
For an RPG CGI program to be truly useful, you really have to be able to reuse HTML that was developed outside of the RPG program itself. That’s because, although you can build any HTML stream in an RPG program, the process of doing so quickly becomes cumbersome. Imagine trying to build a Web page like www.itjungle.com from within an RPG program. You would have to know where to precisely place your text and tables and images and links and so on, all from within your RPG application. What a nightmare! Besides that, RPG programmers should not necessarily be HTML programmers, too. There is a real art to creating useful, easily navigable Web pages, and, let’s face it, unless you have some basic artistic flair, the Web pages that programmers build typically tend to be boring and somewhat hard to use. There’s a reason why larger shops have a whole section of their IT departments that does nothing but program HTML. They do it because they are good at it. You are good at programming. You should do what you do best and leave the rest to someone else. By using existing HTML created by others, you can have the best of both worlds in your RPG CGI programs. In any event, building dynamic HTML on the fly in RPG has its place, and I’ll show you just where that place is, but for production level Web serving, you need to allow those who do it best to create your Web pages, and all you need is an alternate way to access it.
REUSING HTML FROM A DATABASE
One method that would allow you to reuse HTML would be to store that HTML in an iSeries physical file. Since HTML is really nothing more than text, storing that text in a physical file is a piece of cake. By storing the HTML code in such a manner, at the point in your RPG CGI program where you were going to build an HTML string that you would then push to the browser, through the CGI API, you could read the physical file records instead, and as you read each record, you could write it to the browser, via the CGI API. This process works very well and is probably the easiest method for reusing HTML.
The biggest drawback to this method is that, after someone else creates the HTML document, you have to somehow copy it from his PC to a physical file on the iSeries. Granted, you can do this relatively easily using the Copy From Stream File (CPYFRMSTMF) command, but it can be a real maintenance nightmare keeping the actual HTML document and the document stored in the physical file in sync every time a change is made to the document.
REUSING HTML FROM THE IFS
A better way of reusing HTML is to store the HTML document in the iSeries Integrated File System (IFS). That way your HTML developers can work on the HTML file “in place.” When the HTML developers make a change to the document, that change is immediately reflected in the user’s browser because your RPG CGI program will read the HTML document from where it is stored in the IFS.
We’ll use the Unix-type APIs to read the HTML document stream file from the IFS into your RPG program. Rather than reinvent the wheel here, however, I will point you to an article I wrote on this very topic, “Reading an IFS File from RPG.” Read the article and try out the sample code until you are comfortable with the technique.
As you saw from “Reading an IFS File from RPG,” it is relatively easy to take advantage of the Unix-type APIs to read a file from the IFS. To use that data, just read in your CGI program; to push it out to the Web, just load the data read into a variable and pass that variable to the QtmhWrStout CGI API, which writes the data to your user’s browser.
So how does this work? The way I do it is pretty simple. I create an HTTP Server instance and directory structure, as explained in “Step by Step: RPG IV and Interactive Web Pages,” and store all of my HTML documents in one of the directories below the /htdocs directory in that directory structure. If you’ve followed all the steps in the previous article, you know how you can access the Web pages in that directory by using the URL http://yourAS400IPAddress:YourPort/yourpage.htm. If you have not yet read and tried out the steps described in the previous article, go back and read it first. Otherwise you’ll be totally lost with the rest of the information in this article.
What we want to accomplish for the example, as well as for production-level RPG CGI efforts, is to be able to open any pre-defined Web page stored in the iSeries IFS and to display that Web page in the user’s browser. In addition, we need to have some way to know, programmatically, what is the next Web page to open, based on the current Web page. In other words, if a Web page named “customer.htm” is currently the active Web page in the user’s browser, and the user enters a customer number to view that customer’s detail information, we need the RPG CGI program to somehow know that the next Web page to display is “customerA.htm,” because “customerA.htm” contains the HTML for the customer detail. How do we do this?
We do it by defining a hidden HTML input field in every Web page we will read into our RPG CGI program. We will name this field “NEXTPAGE” and define it like this:
<INPUT TYPE="TEXT" HIDDEN NAME="NEXTPAGE" VALUE="/customerA.htm">
In addition, so that we know what the current page is, we can define another HTML field named “PAGEID,” like this:
<INPUT TYPE="TEXT" HIDDEN NAME="PAGEID" VALUE="customer.htm">
In order for the RPG CGI program to be able to read these fields when the user presses the “HTML Submit” button, we must first define those fields in the database that we identified as the file layout the CGI program should use to parse the HTML form data. Again, if you did not read the previous article, this last bit of information probably made no sense whatsoever, so please go back and read and try out the example code in the other article before continuing.
When the user presses the “Submit” button on the Web page, the RPG CGI program is invoked, which then parses the fields from the HTML form, reads the PAGEID field to see what the current page is, checks its internal logic to see if it has any instructions for that page, and, if so, does whatever it needs to, perhaps validating a customer number to see if it is on file. Finally, the RPG CGI program reads the value of the NEXPAGE field to see what the next page is that should be opened, and then the Unix-type APIs are used to open that Web page, to read its content into a variable, and that variable is then passed to the QtmhWrStout API to be displayed in the user’s browser. Complex to talk about, but actually quite simple in practice. Check out the RPG CGI sample program that accompanies this article for a complete working example to see all of this in action.
The only caveat I want to offer here is that you ensure that both *PUBLIC and the QTMHTTP user profile have enough authority to both the directories and the actual HTML documents that you are attempting to open with the Unix-type APIs. If there is insufficient authority to either one, you will get a “page not found” error when you attempt to display it in the user’s browser.
PREFILLING HTML FORM FILES AND ADDING DYNAMIC HTML
The final bit of knowledge you need to make your RPG CGI programs truly dynamic is the capability to add changeable content to an existing HTML page and to be able to pre-fill fields on an HTML document before displaying it in the user’s browser.
Adding dynamic, or changeable, content to an HTML document is actually pretty simple. The way I do it is to create a variable in my RPG CGI program (call it “newHTML,” for example) and build my dynamic content inside that variable. Say that you have a Web page that has the following HTML code in it:
<TABLE><TH>Customer #</TH><TH>Credit Limit</TH></TABLE>
You somehow want to get the contents of one of your OS/400 databases, inside of that table, formatted so that the customer number is in the left hand column and that customer’s credit limit is in the right hand column.
To accomplish this feat, we’ll take advantage of a bit of RPG IV string manipulation and the fact that HTML is really nothing more than one long character string.
To do this, we will use a combination of the %SCAN and %REPLACE built-in functions in RPG IV. Within the Web page where we want to display the customer’s name, we add a string to the HTML code: <REPLACEMENTDATA>.
In our example, <REPLACEMENTDATA> is placed between the opening <TABLE> and closing </TABLE> tags. What we will do is to add a new row to that table based on the contents of the database read into the RPG CGI program. (Don’t forget to add some sample records to the CUSTDB database that accompanies this article!)
After we have read the HTML in from the IFS in our RPG CGI program, and have loaded that data into the variable named “newHTML,” we use a combination of %SCAN and %REPLACE to search for that string <REPLACEMENTDATA> and then replace whatever “fields” in the HTML we want, with the actual data from a database. In this case, we can read the CustDB database for the selected customer number and build some simple HTML code to add that customers’ number and credit limit to the HTML table. Something like this:
'<TR><TD>' + %Trim(CustNo) + '</TD><TD>' + %Trim(CLimit) + '</TD> </TR>'
This bit of code will add a new row to an HTML table, containing the customer number and the customer’s credit limit from the database you read in your CGI program.
In addition, what would also be cool would be to have the customer’s name appear in the CNAME field once the user selects a customer, say by inputting a customer number on a previous Web page. In our database, there is a field named CNAME. CNAME will contain the customer name associated with a given customer number. We want to be able to display that customer name on the Web page when a customer number is selected. To do this, we use the same technique of doing a %SCAN and %REPLACE to search for the HTML field named CNAME in the Web page and then adding a VALUE= parameter containing the customer name from the database to that HTML field. And then, finally, adding all of that to the newHTML variable and writing it out to the user’s browser.
TRY IT AND SEE
Sometimes it is a lot easier to understand how something works by trying it out first. That is what you should do here. Download the accompanying ZIP file for this article and upload the code to the same CGIDEMO library you created when you went through the steps in “Step by Step: RPG IV and Interactive Web Pages”. In addition, upload the “.gif” and “.jpg” and “.HTM” files in the ZIP file to the /www/demo/htdocs directory on your iSeries. Note that, in the example HTML, the images are stored in a subdirectory named images. You do not necessarily have to do it that way, but if you do, do not forget to create that images subdirectory below /htdocs. Also, don’t forget to change the URL for the location of the images in the sample HTML and the location of the CGI program specified on the <i>ACTION</i> parameter of the