Message files can simplify many redundant programming tasks when used correctly. Status messages, notification messages, and even multilingual code can all be done with message files. Maintenance to reports and displays can also be done using message files, and no recompiling of any source.
If we are to be considered top-level employees, we must always find ways to be more productive or do what we do in less time. Such accomplishments stand out when it comes to review and raise time. I will let you in on a secret: Message files can help you achieve these goals. In this article, I will talk about what message files are, who needs them, and how they can save programmers time and make them more productive.
Message File Basics
To explain message files, consider the case of an item master maintenance program (you could substitute customer master maintenance, vendor master maintenance, etc.). When a user tries to add an item number that already exists in the database, you would want to warn the user of that fact. The same case holds true when a user attempts to maintain an item that does not exist in the database.
Somewhere in the code, you probably have warnings such as item number already exists and item number does not exist to handle these situations. In all likelihood, you hardcoded those text messages in a line of DDS or maybe even in a high-level language (HLL) program.
In addition to the maintenance program, you have the associated inquiry program that allows users to check an items status, minimums, whats in stock, whats on order, and the like. This program utilizes the same logic as the maintenance program and requires the same type of text messages.
Message files allow you to write a message once and access it by a message number instead of by keying in text multiple times in multiple programs. In this respect, the message file can be a real time-saver. You can also use message files to ease the strain of maintaining multiple national languages. Rather than rewrite code for multiple languages,
simply create message files in English, French, German, or whatever languages you need and point to those files by message number. This is a huge time-saver.
Messaging 101: Creating and Maintaining Message Files
How do you create and maintain message files? The message file object has a unique type on the AS/400, *MSGF. Use the Work with Object (WRKOBJ) command shown below to see what message files the AS/400 has at V4R2. (Figure 1 shows that there are several.)
WRKOBJ OBJ(*ALL) +
TYPE(*MSGF)
To look at message files, you can use the following commands: Create Message File (CRTMSGF), Work with Message File (WRK-MSGF), Work with Message Descriptions (WRKMSGD)a personal favoriteand Add Message Description.
Lets first take a look at one of the most commonly used message files, QSYS/ QCPFMSG. Using WRK-MSGD, you can see that message file QCPFMSG contains many messages, as listed in Figure 2. You can use the blank at the top of the screen to position the display to a particular message number. Examining this list closely would reveal many messages that you see daily when working on an AS/400.
Now that you know what a message file looks like, its time to create your own and get started with messaging. The command below creates a message file in library QGPL, which should be in most users library list.
CRTMSGF MSGF(QGPL/TIMSGF)
The ADDMSGD command gives you one way to add messages to your message file; however, my favorite command, the WRKMSGD, allows you to see what messages a file already contains and to add messages when necessary. To add messages now, type the following at a command line:
WRKMSGD MSGF(QGPL/TIMSGF)
Figure 3 shows that no messages exist in this message file yet. By pressing F6, you can create a message. F6 calls the ADDMSGD command and fills in the message file and library for you. First, you must give the message a seven-character alphanumeric identifier. OS/400 forces you to use exactly seven characters. With displayable messages, I use a three-character prefix to identify the type of message (e.g., INV indicates inventory, ACP indicates accounts payable, SAL indicates sales). You might also choose a three-letter abbreviation of your companys name to serve as a prefix for messages that cross the defined types or have no natural home of their own. Then, you can follow the prefix with an incremental four-digit number. This nomenclature is only a suggestion; your needs may differ. All you need is one alpha character in the message number.
To continue with the inventory example above, create a message and number it INV0001. The first parameter that you need to supply is the Message ID (MSGID), which we will enter INV0001. For the next parameter, the Message (MSG), key in the text of your message: Item number already exists.
The second-level text (SECLVL) is helpful if your users are tuned to positioning the cursor on the message and pressing F1 on a message. It can contain further information to help describe the message or can tell the user what to do. This help text also shows on job logs if you have the second-level text (LOG (4 0 *SECLVL)) in your job description. For this example, I will leave it blank. The severity of a message can be set to cause a message queue to break (automatically appear) with certain priorities. For now, leave it at the default of 00. Figure 4 shows what your display should look like. Pressing Enter completes the
addition of your first message. If you press F5 to update your display on WRKMSGD, you will see the message just created.
Messaging 102: How Can We Use Message Files?
Two common uses of message files are to send messages to other message queues and to display messages from a program. First, I will look at sending messages.
Suppose you need to send a completion message to let a user know that a job, such as a backup, completed. Like many programmers, you probably have a recurring use for that message. First, you would add a message in your message file and call it, for example, HAP0001 (the generic prefix for my company plus an incremental number). Supply Backup completed as the text of the message. Then, in the body of a CL program, send that message to the system operator using the Send User Message (SNDUSRMSG) command.
SNDUSRMSG MSGID(HAP0001) +
MSGF(QGPL/TIMSGF) +
TOMSGQ(*SYSOPR)
That message would be sent to the system operator message queue. This command enables you to send messages to the system operator message queue or the programs external message queue (TOMSGQ(*EXT)). As an alternative, you can use this command to send messages based upon the job type (TOMSGQ(*)); for example, messages for interactive jobs go to the jobs external queue, and messages for batch jobs go to QSYSOPR. I will explore the external message queue later in this article.
Send Program Message (SNDPGMMSG) is another command that uses message files. You could notify the system operator with this command within a CL program:
SNDPGMMSG MSGID(HAP0001) +
MSGF(QGPL/TIMSGF) +
TOMSGQ(*SYSOPR)
You may use message files in certain commands and must not use them in others. (Figure 5 lists those commands that support the use of message files and those that do not.) This is an unfortunate but not insurmountable situation. If you need message text on the Send Break Message (SNDBRKMSG) or Send Message (SNDMSG) command, you can use the Retrieve Message (RTVMSG) command.
Suppose, in the completion message example, that a workstation message queue needed to be notified immediately. SNDBRKMSG is the command to use. The example CL program in Figure 6 shows how to retrieve the completion message description via RTVMSG and pass it on to the SNDBRKMSG command. Although the sample program uses an 80-byte variable, you can retrieve longer variables; the limitation on SNDBRKMSG is 512 characters. If the message length exceeds the width of the display, the message wraps to another line, but not in the way that a word processor performs word wrapping. That you must handle within the message text.
When notifying QSYSOPR, it really does not matter which command you use when in a CL or HLL program. Either command works fine.
SNDPGMMSG has some options that could come in handy in other applications. You can send messages to your interactive display or to a job log for a batch job about the status of a long-running program. To send a message to a job log, do not specify a message queue (TOMSGQ). The default for that parameter is called program message queue.
You can easily test this by creating a short CL program using the two messages that you have created already. Compile the four lines in Figure 7 and call the program QCMD/QSYS. Then, call the program and press F10 from QCMD. You should see the messages Backup completed and Item number already exists.
Have you ever run a query or a backup and noticed the messages that flash across the bottom of your screen? Like the TV show, have you ever wondered, Howd they do that? Heres your chance to find out. Youll use SNDPGMMSG in this example also.
In the previous example, you made sure the message went to the programs message queue. If you change some parameters just a little, you can see the messages flash along the bottom of the screen. This time, you send a status message type (MSGTYPE(*STATUS)) to the programs external message queue (TOPGMQ(*EXT)). The code to accomplish this (see Figure 8) contains a Delay Job (DLYJOB) command to allow time to view the messages.
Messaging 103: Message Files as Literals
Did you know that you could use message files with DDS specs for screen and printer output? Most definitely.
Imagine that you want a change to a report in a normal program (HLL program and DDS output, or output in the HLL program). If you used externally defined printer specs, you would have to recompile the DDS and then recompile the HLL program. If you had your report embedded in an HLL program, you would just have to recompile the program. What about making changes without recompiling a program? Its possible.
Lets take an example of an HLL program with externally described printer specifications in DDS. Figure 9 contains an example of typical output specs, and Figure 10 shows the same specs using message files. In this simple example, you save two lines of coding in the DDS, plus you make it maintainable without recompiling. Heres how.
In your message file (QGPL/TIMSGF), add one more messagea literal for what the HEADER1 line would look like when printed. Here its called L000001, for literal number 1. With the immensity of possible literals, you can choose to use only one character for the message identifier, leaving enough room for 999,999 (L000001 through L999999) literals.
After creating the literal, use the message constant (MSGCON) keyword in your printer specifications and tell it how long the literal is, the message number, and the message file. To do this, you need to place the message file in your library list or qualify the message file on the MSGCON line. You simplify things by having the message file in your library list.
Does that seem easy? It is. One of the advantages of using message files as literals in display and printer files are for multilingual applications. Just as you used it here in a printer file, you can also use it in a display file. Without message files, imagine the headache of keeping one source library for English, one for French, one for Spanish... The list could be virtually endless. Using message files, you can keep a single English message file, a French one, a Spanish one, and so on. The maintenance is much easier and involves no recompiling.
Final Exam
Message files can help programmers in many ways. Their use can simplify error messages, completion messages, and display and printer file modifications. Your assignment is to look in your environment to see where you can simplify tasks and save time with message files. You might spend some time up front modifying your code, but you will reap long-term productivity gains by using message files.
Reference
OS/400 CL Reference V4R1 (SC41-5722-00, CD-ROM QB3AUP00)
Figure 7: Program message example
PGM
SNDPGMMSG MSGID(HAP0001) MSGF(TIMSGF) TOPGMQ(*EXT) +
MSGTYPE(*STATUS)
DLYJOB DLY(5)
SNDPGMMSG MSGID(HAP0001) MSGF(TIMSGF) TOPGMQ(*EXT) +
MSGTYPE(*STATUS)
DLYJOB DLY(5)
ENDPGM
Figure 8: Status message example
A R HEADER1
A SPACEB(1)
A 1'ITEM'
A 17'DESCRIPTION'
A 49'CLASS'
A R DETAIL1
A SPACEB(1)
A ITEMNO 15 1
A DESCR 30 17
A CLASS 2 50
Figure 9: Typical output specs
A R HEADER2
A SPACEB(1)
A 1MSGCON(00054 L000001 TIMSGF)
A R DETAIL2
A SPACEB(1)
A ITEMNO 15 1
A DESCR 30 17
A CLASS 2 50
Figure 10: Message file output specs
LATEST COMMENTS
MC Press Online