Profound Pro Tips is a blog series that is focused on reoccurring customer issues that our support team receives and aims to answer questions our Profound Logic customers might have before they even have them! Many of our customers have similar questions and concerns which lead us to create Profound Pro Tips... an easy to reference set of reoccurring questions you might have. Don't see your question/concern in Profound Pro Tips? Please feel free to submit a support ticket and our amazing support team will be happy to help any way they can or leave us a comment below and we will pass it along to our support team.
This week one of our Jr. Developers Matthew Denninghoff (who will be speaking this year at PLUS '17) discusses how to troubleshoot universal display file programs...
This entry will be primarily for those developers who are new to Universal Display Files.
This tutorial covers some problems that a developer may experience the first times developing Universal Display File programs. We will discuss how to find the correct job to debug. This tutorial assumes you have familiarity with using the Universal and Visual Designers, including binding fields, saving, and compiling. The tutorial assumes you are familiar programming in RPG.
A first Universal Display File program may be simple, such as this:
The display file may output a simple HTML document. It has a header, a record that is output once for each file entry, and a footer:
The fields are setup as Reference Fields:
After saving and compiling the file, it is finished.
Next, an entry is added to the PUIMAPP file, the Universal “Web Connector.”
Then the program can be called from a URL like: http://power8:8540/profoundui/universal/blog1
When attempting to load that URL from a web browser, the page seems stuck waiting. Something is wrong. Look for a job in MSGW status in the WRKACTJOB command.
View the message (option 7):
(The job log, viewed by pressing F10):
Look at the bottom of the job log. (The IBM HTTP Server provided by Apache reuses CGI jobs instead of creating new ones, so some of the messages may belong to other, unrelated requests.) The file could not be found, because the library list for a UDF program called directly from the URL is just the library of the Profound UI instance—MDTEST in this case.
Since the physical file, BLOG1P, is in a different library, we must provide the RPG program a way to find the file.
Later, we’ll discuss a way to avoid hard-coding any library names into the program. But to test it now with the browser, we add a EXTFILE('LIBNAME/BLOG1P') keyword to the “DCL-F BLOG1P” line. If we recompile and run, then we get another error, CPF9812:
The display file could not be found. Like with the physical file, the display file is not in any library in the library list. If we add the EXTFILE('LIBNAME/BLOG1UD') keyword to the display file declaration, then our test will succeed—the browser successfully receives a response:
UDF programs are not always meant to be loaded directly in a browser’s address bar. Often, there is an active Profound UI session, and some background JavaScript requests data from the UDF program’s URL.
When an “AUTH” parameter is passed to the URL, then the Universal “Web Connector” automatically synchronizes the session’s library list with the UDF job. Because of synchronization, the RPG program can find the external files without hard-coding libraries. We’ll create an example.
A Rich Display program could load Universal Display file data using at least three different methods.
- The AJAX Container widget. Useful if the program at the URL responds with pre-formatted text, such as HTML. This is easy to setup.
- An IFrame widget, which is little more than a HTML IFrame. Can be used if the responding program sends HTML text. Necessary if the HTML page should be navigable (links can be clicked to load new pages, etc.). IFrames are also easy to setup.
- Custom JavaScript that parses the response and populates an HTML Container widget. If the response data is JSON or XML, then it must be parsed and formatted before being output to the user. This setup requires some JavaScript coding knowledge.
First, we will see how to setup methods 1 and 2. Here is a look at an example display file in Visual Designer:
The RPG code to drive it is here:
To setup the AJAX container, simply set the “ajax url” property. If the Universal Display program needs to synchronize its job with the session job, then the URL must be passed an “AUTH” parameter. To do so, a script must set the URL:
script: document.location.protocol + "//" + document.location.host + "/profoundui/universal/blog1?AUTH=" + pui.appJob.auth
The “script:” portion tells Profound UI to expect JavaScript. The document.location variable is useful to avoid hard-coding “http”, the domain, and port number into the display file. The pui.appJob.auth will contain a Profound UI session ID. When you click “OK” on the editor, you’ll get this message:
Ignore the error. Visual Designer runs the script to check it, but the pui.appJob object is only set when the program runs, not within Designer.
To setup the IFrame, just set the “iframe url” property to the same value:
Press OK, and ignore the error.
When the display files and RPG programs are compiled, and the Rich Display program runs, then the output from our Universal Display file shows up like this:
That concludes this example. We’ve seen two simple ways to pull in extra content into a Rich Display File without coding the file-reading logic into the Rich Display program.
Now we’ll look at the third method of loading UDF data by sending unformatted JSON data and using it.
The RPG can be the same, but the Universal Display file content contains JSON instead of HTML. Also, the “document type” is set to “json”, and the “record” format has the separator property set:
We reuse the same Universal Display File RPG program by changing the “DCL-F BLOG1UD” to “DCL-F BLOG2UD”.
We will create a different Rich Display File with just a HTML container and a button with its response bound to and indicator named, “btnexit”:
The container requires no setup. To get the JSON data into the container, we will setup the screen’s “onload” property with some code:
var htmlc = getObj("HtmlContainer1");
var list = ajaxJSON( document.location.protocol + "//" + document.location.host
+ "/profoundui/universal/blog1?AUTH=" + pui.appJob.auth );
var htmltext = '<ul style="list-style-type:none">';
if (list != null && typeof list == "object" && list.length > 0){
for (var i=0; i < list.length; i++){
htmltext += "<li>" + list[i].filmrank + " – "+ list[i].filmname + "</li>";
}
}
htmltext += "</ul>";
applyProperty("HtmlContainer1", "html", htmltext);
This code runs when the screen loads and requests the JSON text from the Universal Display file. If the response was good, then the JSON data is a JavaScript list of objects. The code writes each list element into an HTML unordered list tag string, <li>. Then the HTML Container gets the html string as its contents via the applyProperty function.
When we compile our display files and RPG programs, and we run the rich display program, the results look like this:
For this example, the JavaScript and JSON method is more complicated than the HTML Iframe or Ajax Container. However, the JSON data output by the 2nd UDF program could be used in more ways than just displaying. The JSON data could become the source for a subfile, a chart, a combo list, or an auto-correct to a text box.
Another reason to use the JSON method is if you are following a Model-View-Controller paradigm. The UDF is part of the Model, and the model should not contain formatting information—the HTML and style. The Rich Display File program would be part of the View, and that would be the piece that should format the JSON data.
Why aren’t my changes taking effect?
The system may cache the RPG program for the lifetime of the job. You may change and recompile the program and try to load it, but the HTTP server uses the cached program. To ensure that the latest program is run, you should end the CGI job that is running the UDF program.
You can find the job in WRKACTJOB, then end it with the *CNTRLD option with a short delay:
With HTTP server jobs, it’s important to use *CNTRLD and not *IMMED. To find the correct job to end, continue reading.
How do we find the job for the UDF program to debug it?
If you are having trouble with a Universal Display File program, you can temporarily add debugging text to its output, or you can use a debugger on it.
To attach a debugger, you can start a service job to listen for the program called by a certain user profile. This approach works if the Rich Display File program loads the UDF program with the “AUTH” parameter. If the RDF session is anonymous and the library list includes the library containing the UDF display file and the file the UDF program reads, then debugging via service jobs will also work.
If the UDF program is not loaded with the “AUTH” parameter, then its CGI job is not associated with a regular user profile. Instead, the job’s current user is QTMHHTP1, as shown in WRKACTJOB:
To debug this job in RDi, you can attach the service job to the QTMHHTP1 user profile.
You can also debug using the IBM i STRSRVJOB and STRDBG commands. You’ll need the job’s user, name, and number:
Then you can start a service job, then start debugging. For example:
STRSRVJOB JOB(084028/QTMHHTTP/MDTEST)
STRDBG PGM(BLOG1R)
Then, the debugger will pause on your breakpoint when the CGI program is loaded:
What if your UDF program is being used anonymously—it’s not called with the “AUTH” parameter—and you have trouble finding its job?
This situation can happen when there are many different CGI programs being run. To find the correct job, you’ll need to inspect the job log of each and look for clues to which CGI program is running. It may help to add some print output to the job log for the UDF program you’re developing:
Once Qp0zLprintf is writing to the job log, then it should be simple to identify the program running in the CGI job.
Note that when jobs have been running for a long period, the HTTP Server likely reuses them for various tasks. The job log will contain information from those unrelated programs. Therefore, it’s important to look at the bottom of the CGI job’s log:
You should be able to find the correct CGI job using the methods covered so far. If you are still having trouble finding the correct job, then you may need to resort to trial and error: look at each CGI job that seems likely to be running your program, do STRSRVJOB and STRDBG, and set a breakpoint. If the breakpoint isn’t hit, then look at the next CGI job and try again. The CGI jobs can be identified in WRKACTJOB by looking for “PGM-QZSRCGI” in the Function column.
It may also be helpful to restart the instance of Profound UI in which you are developing the UDF program. If you are developing in your own test instance that only you use, then this method will end all jobs and start only the ones that you cause the start.
November 15th-17th Profound Logic will be hosting our 2nd annual PLUS Seminar for their customers. Get the most value from your Profound Logic investment and assure your modernization success. Register here today!
One of our focuses for 2017 is the continued adoption of Node.js in IBM i shops. Click here to read our white paper on Why Node.js Is The Solution Your Company Needs.
Also, Profound.js 2.0 has been released! See how Profound.js 2.0 can help modernize your IBM i today!