TechTip: Program Messages 101 PDF Print E-mail
Tips & Techniques - RPG
Written by Joe Pluta   
Friday, 10 January 2014 00:00

Support MC Press - Visit Our Sponsors

Forums Sponsor

POPULAR FORUMS

Forums

Search Sponsor

POPULAR SEARCHES

Search

Program messages are a fundamental part of the operating system, and the more you know about them the better.

RPG has come a long way from its original, standalone report-generation days. We can integrate features from many other languages and from the operating system itself via simple calls. That additional functionality, though, leads to additional complexity. Many times, errors occur under the covers of our RPG programs, and while often it's enough just to know an error occurred (say on a file open), sometimes it's important to know the details of the error. The IBM i has a powerful messaging system that allows you to get that information, but you need to access it. This is the first in a series of tips that will help you do just that.

Getting the Last Error Message

In this tip, we'll extract the information from the most recent error message. This technique can be used whenever an error occurs. First, be sure to capture the error and prevent it from causing a hard halt. You can do this with the (e) extender on the opcode or by wrapping the operation in a monitor block. You can even go old-school in RPG III and use an error indicator on the operation.

 

When an error occurs, the error message is logged in the program message queue. You see the contents of that queue whenever you display the job log for a running job, or in the joblog spooled file that is created when the job ends. While those somewhat indirect methods are the usual ways we see program messages, we can also access the messages in the queue directly using standard IBM i commands, and this article shows you how to do it.

 

Before I get to the code, though, we need to take a closer look at the IBM i's messaging system and specifically at how messages are defined and presented to the user. One way to think of a message is as a form letter. Each message has a key (a seven-character message ID) and then it has message text. Most messages also have substitution variables, which act as holding areas in the message text for dynamic data to be passed in when the message is sent. At presentation time, the variable data is merged into the static message text to create the final message. For example, error message CPF0001 has the text "Error found on &1 command" along with a single substitution variable. The variable is a character field with a length of 10, which is perfect for holding a command name.

 

Go to an IBM i command line and type the command JOEPLUTA. Assuming you don't have a command named JOEPLUTA on your system, you will see two messages:

 

Command JOEPLUTA in library *LIBL not found.

Error found on JOEPLUTA command.

 

The first is message CPD0030, while the second is the CPF0001 message I already mentioned. When the operating system sees that the JOEPLUTA command is not found, it sends out both messages. When it sends out the CPF0001 message, it includes the command name as part of the message data. The command line processor then merges the text and presents it to you.

 

That merged text is for human consumption. But the underlying architecture of using message data makes it very easy for programs to access the original information and interact with those messages. Imagine if we had to find the program name from the actual test displayed. It's not particularly hard, but this is a simple message with only one parameter. And even this one can get difficult; imagine if you're running on a Spanish-language machine. Any hardcoding you did for "Error found on" now goes out the window.

 

So, the idea is to be able to extract the message ID and the unformatted message data. Today's tip goes that first step by giving you a simple CL program that retrieves the ID and message data for the most recent message. You might be thinking to yourself that we've gone a long way into the tip without seeing the code, but that's because the code is so very simple:

 

GETPGMMSG.CL

 

GETPGMMSG: PGM       (&MSGID &MSGDTA)

             DCL       &MSGID *CHAR 7

             DCL       &MSGDTA *CHAR 500

 

             RCVMSG     PGMQ(*PRV) MSGQ(*PGMQ) MSGTYPE(*LAST) RMV(*NO) +

                         MSGDTA(&MSGDTA) MSGID(&MSGID)

 

             ENDPGM

 

 

That's it. You call this program with two parameters, a seven-character message ID and a 500-character message data parameter. The length of the message data parameter is arbitrary; you can use whatever best suits your environment. Then, whenever an error occurs, just call the program. Here's a rather contrived example:

 

     d x             s             3u 0

     d y             s            3u 0

 

     d GETPGMMSG     pr                 extpgm('GETPGMMSG')

     d oMsgid                    7a

     d oMsgdta                500a

 

     d msgid         s             7a

     d msgdta       s           500a

 

     /free

    x = 0;

      monitor;

       y = (1 / x);

      on-error;

       GETPGMMSG( msgid: msgdta);

      endmon;

      *inlr = *on;

     /end-free

 

Run this program in debug and step through. Since we're dividing by zero, you'll find yourself executing the on-error clause, which in turn calls the GETPGMMSG utility. This is a very simple case; the error received (MCH1211) is one of those rare messages that has no parameters at all. It basically just says that divide by zero occurred, and that's all you need to know. So if you step through the call you'll see that afterward the variable msgid contains the value MCH1211. And that shows that the utility works as designed!

 

It's kind of funny, actually, that the test program has more lines than the utility itself, but that's sometimes the case and especially in this case where I've shown you only a very limited use of the program message APIs; in subsequent tips, we'll extend this utility quite a bit.

 

Enough for now. Start playing!

 

 


Joe Pluta
About the Author:
Joe Pluta is the founder and chief architect of Pluta Brothers Design, Inc. and has been extending the IBM midrange since the days of the IBM System/3. Joe uses WebSphere extensively, especially as the base for PSC/400, the only product that can move your legacy systems to the Web using simple green-screen commands. He has written several books, including E-Deployment: The Fastest Path to the Web, Eclipse: Step by Step, and WDSC: Step by Step. Joe performs onsite mentoring and speaks at user groups around the country. You can reach him at joepluta@plutabrothers.com.

 

MC Press books written by Joe Pluta available now on the MC Press Bookstore.

 

Developing Web 2.0 Applications with EGL for IBM i Developing Web 2.0 Applications with EGL for IBM i

Joe Pluta introduces you to EGL Rich UI and IBM’s Rational Developer for the IBM i platform.

List Price $39.95
Now On Sale
 
WDSC: Step by Step WDSC: Step by Step
Discover incredibly powerful WDSC with this easy-to-understand yet thorough introduction.

List Price $74.95
Now On Sale
 
Eclipse: Step by Step

Eclipse: Step by Step


Quickly get up to speed and productive using Eclipse.

List Price $59.00

Now On Sale
 
Read More >>
Last Updated on Friday, 10 January 2014 00:00
 
User Rating: / 1
PoorBest 
   MC-STORE.COM