My previous articles on CGIDEV2 ("Getting Started with CGIDEV2 – Part 1", "Getting started with CGIDEV2 -- Part II" and "Getting Started with CGIDEV2 – Part III"), concentrated on developing CGI programs using external HTML and the procedures provided by CGIDEV2.
You may be one of those talented programmers whose programs always work the first time, but lesser mortals like me run through the usual routine of having to test and debug programs before they provide any form of sensible output. In this article I want to discuss some of the considerations for debugging CGIDEV2 programs.
The error detection and debugging process for CGI style programs is, potentially, a lot more complex then normal interactive or batch programs (did I say normal?) simply because there are more possible areas for failure. There could be a problem in the configuration of the server, in the coding of the HTML, or even in the logic of your program -- unthinkable as that may be. To compound this, it isn't always clear what has actually failed. You might get a message in your browser that simply says "The page cannot be found" (a HTTP 404 error), which could mean that it cannot find the program or the program failed to run or -- who knows?
So let's look at the steps you take to debug CGI programs along with one of the excellent tools that CGIDEV2 provides to make the debugging process even easier.
The right environment
You can make life a lot easier for yourself by ensuring you have the correct test environment for your development. It is best to create a server instance with a unique port because chances are you will need to stop and start the server a number of times. This also makes the required server jobs easier to find.
A quick way to determine if you are having a program error or a configuration error is to simply call the program from a command line. If the HTML flashes on the screen and you return to a command line, it is a good indication that the problem may be a configuration error. But only maybe -- it could well be that the problem is caused by a value being entered in a form.
The Apache server
The first place to start the error detection and debugging process is with the Apache server. By default, the Apache server maintains an access log and an error log for your server. If you have taken the defaults for the configuration of the server, these logs will be in the directory www/server_name/logs (where server_name is the name you gave your server). The log files will be named access_log.Qcyydddss and error_log.Qcyydddss where c is the century, yyddd is the julian date and ss is a sequence number.
Personally, I find the easiest way to check these logs is to enter this command:
Then use option 5 to display the contents of the required log file.
Figure 1 shows the contents of an error log. Note the last entry that specifies that a requested URL is not a CGI program -- that is what I get for mistyping a program name. You will probably have lots of annoying messages in your error log regarding a non-existent favicon.ico file. Believe it or not, this is an icon for bookmarks in browsers, and the easiest way to get rid of the annoying message is to create the icon. A quick Google search for favicon.ico will give you plenty of information on how to do that.
Figure 1: Error log for an Apache Server
The access log, shown in Figure 2, shows all access requests for the server.
Figure 2: Access log for an Apache server.
Debug the job
The next place to check is the server job running on the system. The job will have the same name as the server, and you will find it in the QHTTPSVR subsystem. There will be a number of jobs with the same name; the one you are interested in is the one running the function PGM-QZSRCGI.
You can start by checking the job log for the server job and see if there are any obvious messages such as decimal data error or file not found or any of those programming errors we know so well.
You can also debug the job just as you would any other batch job. Use the Start Server Job (STRSRVJOB) and Start Debug (STRDBG) commands on green screen, use the Distributed Debugger that is provided with CODE, or use the debugger in WDSC. Figure 3 shows an example of a CGIDEV2 program being debugged using the Distributed Debugger -- simply because it is the debugger I find easiest to use. Of course the program must have been compiled with the requisite debug view (the DBGVIEW keyword on the CRTBNDRPG or CRTRPGMOD command).
Figure 3: Using the Distributed Debugger to debug a CGIDEV2 program
Check the HTML
If you manage to get some data displayed on a Web page but it is either incomplete or incorrect, remember that you can always view the HTML source in the browser by selecting View->Source from the menu in Internet Explorer or View->Page Source from the menu in Firefox. You can now compare this with the original HTML source you are using with your CGIDEV2 program and see if there are any differences.
The CGIDEBUG command in CGIDEV2
One of the great features of CGIDEV2 is that it provides a built-in debugging log for your programs. By simply switching on debug (more in a minute) you can get CGIDEV2 to provide a trace log of everything it does. You can even add your own messages to the log.
The easiest way to get ready to use CGIDEUG is to copy all CGIDEBUG objects from the CGIDEV2 library to the library you are using to store your programs. The *FILE and *DTAARA objects are the only two that are absolutely necessary, but you will need CGIDEV2 in your library list or you will need to use qualified command names if you do not copy them all across. If you are using the CGIDEV2-provided Set Libraries for CGI Development (SETCGILIB) command to set up your CGIDEV2 development environment, then these objects will have been copied across.
Figure 4 shows the prompt for the CGIDEBUG command. The second and third parameters indicate the name of the data area used to control CGIDEBUG and the library for the data area. I like to go with the defaults, so I usually set my current library to my development library. One of the advantages of having duplicated the CGIDEBUG command is that you can change the defaults if you wish.
Figure 4: Prompting the CGIDEBUG command
To enable CGIDEV2 debugging, you enter the command
CGIDEBUG ACTION(*ON)Now, call the required programs from the browser, and the CGIDEV2 subprocedures will trace their actions in the CGIDEBUG file in the development library.
To display the debug information enter the command
CGIDEBUG ACTION(*DSPDATA)The resulting display is shown in Figure 5. Each line is time-stamped, followed by the CGIDEV2 subprocedure name, followed by the action and/or messages issued for the subprocedure. Messages to watch out for are those that indicate an invalid section or field name or that say starting/ending delimiters are missing for a section or field definition.
Figure 5: Display CGIDEV2 debug data
CGIDEV2 also provides a number of callable subprocedures that can be used in conjunction with debugging:
- wrtdebug() allows you to write information to the debug file
- wrtjobdebug() writes the job name, date and time to the debug file
- wrtpsds() writes the program status data structure to the debug file
- isdebug() indicates whether CGIDEV2 debugging is enabled.
When you have found your errors and corrected them, make sure you switch off debugging by running the command CGIDEBUG ACTION(*OFF), otherwise the debug file will start to get very large very quickly.
You can determine whether debug is enabled by entering the command
You can also clear the debug file by entering the command
Some common errors
Here, in no particular order, are some of the more common errors we all make when using CGIDEV2. The list is by no means complete, so if you have any to add to it please let me know.
- The ScriptAliasMatch is not correctly defined in the server configuration. This is usually indicated if you have to enter an extension of .PGM at the end of the URL or if you are constantly told the program cannot be found. The ScriptAliasMatch should specify
- The content type is not correctly specified in the HTML document. The start of the HTML documents should contain Content-type: text/html followed by two carriage returns/line feed (press return twice). There should not be any erroneous spaces at the end of the first line or on the second line. The sample log shown in Figure 5 shows how the content type should be output. Note the "block" at the end of the lines that indicate carriage return/linefeed.
- It is easy to locate the mistyping of the starting and/or the ending delimiters for section names and/or field names. This usually results in spurious data being displayed on the Web page, and you can check the debug data for details.
- You might also receive security violations because the QTMHHTTP and/or QTMHHTP1 profiles do not have access to the directories being used to store the HTML documents. Remember, the server programs are not running under the profile of the person who logs on.
- You might also receive file not found errors because you are using a library list. Remember, the program is running in a server job in QHTTPSVR, so you cannot depend on a library list.
A final word
I hope these last few articles have at least tempted you to try CGIDEV2. There is nothing quite like getting that first Web program working.
There is also the added benefit of having a whole new means of providing an application interface for your users and even your customers. And all you have to get to grips with is some HTML and a few easy-to-use subprocedures.
In the near future I will return to some of the neat techniques you can use when programming for the Web.
About the author: Paul Tuohy is CEO of ComCon, an iSeries consulting company. He is the author of Re-Engineering RPG Legacy Applications and is one of the quoted industry experts in the IBM Redbook "Who Knew You Could Do That With RPG IV?"
This was first published in November 2005