It never seems to fail; I go to see new clients and find them locked into the old green-screen metaphor. They don't want a GUI because of reason X, Y, or Z. Then, after a few months, corporate management suggests that they want their information available through the Web for easier access.
Suddenly, everything GUI is the technology du jour. Specifically, a Web browser interface is needed, and of course, since the clients haven't done anything with CGI/Web programming or GUI, they go off on a research mission.
The first mistake they make is to expect to use IBM's WebFacing for everything. They soon realize WebFacing is a great technology that's good for a very specific style of applications: flat, green-screen apps that don't use windows or pop-ups and don't stretch what you could do with a green-screen too far. For those old, System/36-style applications, WebFacing is a fine tool for those shops that do not have CGI programming skills. It is also good if you have someone on staff who can follow up on the basic conversion with customizations of the generated JSPs and/or JavaBeans. However, while WebFacing is not a bad tool, it's often abandoned once users see the unusual way the 5250 screen maps to a browser.
The next mistake people make is to consider installing the WebSphere Application Server (WAS). This adds a level of overhead to your system that you just don't need. In addition, you are pretty much stuck using WDSc's development environment to build to the WAS interface. WAS should be considered for huge applications where your entire corporation has committed to it, but for the small-to-medium size AS/400/iSeries/i5 shops, it is just too big (read: bloated) to deal with.
A few shops are choosing the right solution in my view, which is using CGI with RPG IV or JSPs. Both can be hand-coded or automatically generated by one of the third-party tools. JSPs are OK, but this is, after all, RPG Developer, so of course I prefer the RPG IV/CGI approach.
Writing a CGI program in RPG IV requires that you learn the entire CGI process and then apply that knowledge to RPG IV. In addition, you need to learn the APIs that IBM includes with OS/400 to do CGI programming from within RPG IV.
CGI APIs
The purpose of this article is not to teach CGI programming concepts, but to introduce you to the CGI APIs and help you build your first CGI program. IBM includes a set of APIs that provide CGI capability to RPG IV and other ILE-targeted languages. ILE C/400 has CGI capability built in to the language, and there are also several add-on libraries that provide clean and direct CGI support from within C. Therefore, the CGI APIs are not required if you use C or C++.
IBM includes seven APIs for CGI programming. They are summarized in the table below.
APIs for CGI Programming | |
API Name | Description |
QtmhGetEnv | Gets a value from the CGI environment |
QtmhPutEnv | Changes a value in the CGI environment |
QtmhRdStin | Reads a string from the standard input device (i.e., read data sent to a CGI program from an HTML form) |
QtmhWrStout | Writes a string to the standard output device (i.e., write to the Web browser) |
QtmhCvtDB | Converts URL-encoded string to an externally described data structure |
QzhbCgiParse | Parses the data from an HTML form |
QzhbCgiUtils | "Utilities" to create a full HTTP response |
About the Environment
IBM quietly added the UNIX "environment" to OS/400 when they added PASE to the machine. The environment is used by CGI (not exclusively, however) to store and retrieve data. The easiest way to understand the "environment" is to think of it as a positionless data area. The environment allows you to store data in it and retrieve data from it by "variable" name. For example, to store the next available customer number in the environment, you could specify it as a parameter of the QtmhPutEnv, in the following syntax:
NEXTCUST=12345
NEXTCUST is the "variable" or identifier that is assigned to the value, and 12345 is the value that is saved or assigned to NEXTCUST. Later, when you need to retrieve the next customer number, you call the QtmhGetEnv API and ask it to return the value for NEXTCUST, and it kindly returns 12345 to your program. This beats using a data area by at least a factor of 1000.
About Standard In/Out
To send data to a Web browser, you need to route the data through what's called "standard output," which is different from a 5250 green-screen process. Standard output is where commands send their data to; this is UNIX-style I/O. Standard output can be rerouted (similar to an OS/400 file override) to a file or another device. The standard output device is used to send data to the Web browser from RPG IV and other high-level languages (HLLs). IBM provides the QtmhWrStout API to send data through standard output. Likewise, IBM also provides an API to read data from the Web browser: QtmhRdStout, which reads from the standard input device, yet another UNIX-style I/O device.
Copying Data from HTML Forms to Database
IBM also provides a really cool API called QtmhCvtDB. If you have an HTML form that an end user has entered data into and you want to move that data to an externally described data structure, you can use this API. You specify the data structure name and a database format file. The API uses the format file to convert the data from the HTML form into the externally described data structure.
The QtmhCvtDB API is very popular with inexperienced CGI programmers who have written only one or two CGI programs, but they quickly learn that it is really a highly specialized API and widespread use of it is probably not going to save the RPG CGI world.
Parsing Data from HTML Forms
A better and more complex solution to moving data from an HTML form into fields in your RPG CGI program is to use the QzhbCgiParse API. This API is actually a port of a C routine written for another platform. QzhbCgiParse is very complex, and you need to not only read IBM's documentation on it, but also find the source for it on the Internet and read that as well. You might ask, why read the API's source code? Once you read IBM's documentation on QzhbCgiParse, you'll understand why I suggest that you need to go elsewhere for information on this API.
QzhbCgiParse is a favorite tool of experienced CGI programmers. You'll find most generated RPG CGI code uses it, and the two most popular CGI add-on libraries have great wrappers for it as well.
CGI Add-On Libraries
For several years, there has been a little-known service program available from IBM to help simplify CGI RPG programming. This library has moved around on the Web from place to place over the last few years and is, as of this writing, available at IBM's Easy400 Web site. I used this add-on library for years and have programmed dozens of in-production RPG CGI applications using it.
Last year, questions were raised as to the future availability of this add-on library. I made an offer to IBM to make that library available for free from my own rpgiv.com Web site, but those negotiations ended up going nowhere. At that point, I had to make a decision. I decided that hoping IBM would continue to make the add-on library available in the future wasn't a good business decision, so I created my own CGILIB add-on library using the RPG xTools as the underlying infrastructure. Since then, IBM has made the add-on library available at the URL mentioned above.
Today, when I need to create an RPG CGI program, I use CGILIB, an add-on service program for RPG IV. CGILIB contains several helper procedures that make CGI programming simple. The good news is, it is also a free add-on service program. It does, however require that the RPG xTools are installed on your system.
My First RPG CGI Program
To create a CGI program with RPG IV, you need to learn about the CGI process, the CGI method, the CGI program logic flow, API syntax, and standard input/output. With CGILIB, you don't need to know any of that. You just write regular old RPG IV code and embed CGILIB's add-on subprocedures. For example, assume an HTML page has a form on it that requires that the end user enter a name and address. Using CGILIB, you can retrieve the name and address information easily. For example:
C eval CMPNAM = cgiGetVar('COMPANY')
C eval CNTNAME= cgiGetVar('CONTACT')
C eval ADDR1 = cgiGetVar('ADDR1')
C eval CITY = cgiGetVar('CITY')
C eval ST = cgiGetVar('STATE')
C eval EMAIL = cgiGetVarL('EMAIL')
C eval PHONE = cgiGetVarDec('PHONE')
The first line calls the CGILIB initialization routine. This procedure initializes some variables and creates a couple of user spaces in QTEMP. The other lines retrieve the value of each variable entered into the HTML form by the end user. The example uses the cgiGetVar() procedure to read each field's value and store it in your own fields in your RPG CGI program. The cgiGetVar() procedure is a wrapper for the IBM QzhbCgiParse API. It goes directly to the source for the data, and it works very fast.
The last line is a helper routine that returns the data as numeric (decimal). Normally, all HTML form data is returned to you as plain text (i.e., character form only). It is up to you to convert it to numeric if necessary. Since there is no reason to make you do additional work, CGILIB has helper procedures that do the conversion automatically for you. So cgiGetVarDec() returns the value from the HTML form as a decimal. The following is a list of cgiGetVar() subprocedure variations:
cgiGetVar() Subprocedure Variations | |
API Name | Description |
cgiGetVar() | Retrieves a value from an HTML form |
cgiGetVarCnt() | Retrieves the number of occurrences of an individual HTML form field |
cgiGetVarU() | Retrieves a value from an HTML form field and converts it to uppercase |
cgiGetVarL() | Retrieves a value from an HTML form field and converts it to lowercase |
cgiGetVarDec() | Retrieves a value from an HTML form as a decimal value |
cgiGetVarInt() | Retrieves a value from an HTML form as an integer |
In my next issue of RPG Developer, I will continue this thread and illustrate the output capability of RPG CGI. That is, I will illustrate how to write to the Web browser.
Bob Cozzi is a programmer/consultant, writer/author, and software developer of the RPG xTools, a popular add-on subprocedure library for RPG IV. His book The Modern RPG Language has been the most widely used RPG programming book for nearly two decades. Along with others, he speaks at and runs the highly popular RPG World, a conference for RPG programmers.
LATEST COMMENTS
MC Press Online