Stuff
OS/400 Edition
Volume 1, Number 15 -- August 29, 2002

Back To Basics: Message Subfiles


by Kevin Vandever

[The code for this article is available for download.]

TL Ashford Guide Demo Labeling

Many of you have used subfiles at one time or another. You may or may not understand everything about subfiles, but you've probably been exposed to them at some point in your career. However, you've may have missed an opportunity to employ a certain type of subfile, because you weren't aware of it or didn't understand it. In this back to basics installment, I want to touch upon that lesser used but very potent type of subfile: the message subfile.

Get the Message

Message subfiles are special subfiles designed to hold--you guessed it--messages. Message subfiles have some unique properties that make them very useful. They load themselves automatically from messages on a given program message queue. Message subfiles also allow users to view the second-level help text associated with a message, without any additional programming effort. Message subfiles make it possible to setup a consistent set of information, warning, or error messages in a message file for a given program or application, and to display those messages to the user with the greatest of ease. If it all sounds a little too good to be true, you're not far off, but you don't have to pinch yourself to wake up from a dream because it is true. With just a little direction from your RPG and DDS, message subfiles pretty much take care of themselves.

Here is how you use a message subfile:

  • Set up a message file (*MSGF) containing the messages you want to use in your application. You can use an existing message file or create your own. You should not usually modify system-supplied message files, such as QCPFMSG. Message files are created with the CRTMSGF command. New messages can be added via the ADDMSGD command or the WRKMSGF command.
  • Define a message subfile in your display file.
  • Code your application program to send program messages to the program message queue. The best way to accomplish this in RPG is to use the QMHSNDPM (Send Program Message) API. You can also use the SNDPGMMSG command, but the best place to use that command is in a CL program.
  • After displaying the message subfile, clear the messages from the program message queue using the QMHRMVPM (Remove Program Message) API.

For every call stack entry, which can be an OPM program or an ILE procedure, there exists a corresponding program message queue with the same name. This is important to know, especially when you start dealing with ILE and, potentially, multiple call stack entries. The good news is that you don't have to do any work to set up those queues. Just know that with ILE you have to know which call stack entry you are dealing with.

I created my own message file, but you can certainly use the system-supplied messages and plug in your own text. For instance, if users are accustomed to seeing message ID CPF9898 from the system-supplied message file, QCPFMSG, as being something serious, you could still use that message ID and substitute your own message. This doesn't mean you change the CPF9898 message in the actual message file. You simply override the message text in your program. If there are substitution parameters associated with a specific message, you can also fill in those parameters using the program message APIs. If message files aren't your bag, you can also send text messages to the program message queue and use no message file at all. Let's look at some code.

The DDS

In my example, I have setup two messages, SFL0001 and SFL0002, in a message file called SFLMSGF. MSGSFLDF is a display file that demonstrates the use of message subfiles. It consists of three record formats: SCREEN1, MSGSFL, and MSGCTL.

SCREEN1 is the primary screen, and it allows the user to enter data. As you will see in the RPG, this data isn't going anywhere; its purpose is purely to demonstrate how to use a message subfile. MSGSFL is the message subfile record format, and MSGCTL is the control format for MSGSFL. These formats work much the same way as regular subfile control and record formats. There are, however, some differences between regular subfiles and message subfiles.

With regular subfiles, you have to handle the loading and clearing in your program. Typically, in your RPG program, you will set on the indicator used to condition the SFLCLR keyword in your DDS, write to the subfile control format, and set off the indicator to get ready to load and display. With message subfiles, you don't explicitly clear the subfile in your program; rather, you link the subfile to a program message queue and remove messages from that message queue. This, in essence, clears the subfile.

This same theory holds true for loading the subfile. When displaying subfile records in a regular subfile, you must first execute some sort of load routine. This routine usually consists of a DO loop that reads records from a database file and writes them to the subfile record format. Message subfiles will have none of that. By linking the message subfile to a specific program message queue and sending messages to that queue, the message subfile will automatically load itself with records from the program message queue. Message subfiles require the use of several special DDS keywords, listed below.

In the message subfile record format, the following keywords are required:

  • SFLMSGRCD is used to set the starting line on the display for the message subfile. In most cases it is set to 24 (the bottom line of the display), but you could display more than one message at a time, in which case you would set this parameter accordingly.
  • SFLMSGKEY controls the message key of the first message that is to be displayed in the message subfile. Every message on a message queue has a unique message key that is assigned as the message arrives on the message queue. In certain cases, you may wish to maintain old messages on the queue and only display messages from a certain point forward in the message subfile. Setting the message key allows you to control which messages are displayed.
  • SFLPGMQ controls which program message queue the messages are pulled from. In my example, it is being populated with the name of the main procedure from the program status data structure in the RPG program. This technique allows you to easily copy the message subfile record formats into a new display file, with no changes required to the display file. Of course, the SDS_PROC field must be declared in the program status data structure in the controlling program. This keyword also defines the output fields for you. No explicit code is necessary to define your subfile fields.

When in a message subfile, SFLCTL, SFLSIZ, SFLPAG, SFLDSP, SFLEND, and SFLDSPCTL behave normally, except that SFLDSP and SFLDSPCTL must be used without conditioning indicators. Also, SFLPAG must be at least one less than SFLSIZ in a message subfile; they cannot be equal. Message subfiles are considered load-all subfiles. Notice also that I don't use the *MORE parameter on my message subfile. The reason is, using the *MORE parameter causes "More..." and "Bottom" to display one line under the last line on the display. Since I am using line 24, which is the last possible line on the display, I would get an error if I tried to use the *MORE parameter. The plus sign (+) works for me, but if you're dying to use *MORE with your message subfiles, try starting on line 23--SFLMSGRCD(23)--and keeping SFLPAG as 1. Then you won't get an error.

Let's look at the differences in the way two of the keywords behave when they are in a message subfile.

  • SFLINZ, in the case of a message subfile, causes the system to automatically load the subfile with messages from the message queue specified. This is different from its use with regular subfiles. In regular subfiles, SFLINZ loads the subfile with the number of records indicated by SFLSIZ and sets the fields to their default values.
  • SFLPGMQ is used to control which program message queue the messages are pulled from. It is being populated with the name of the main procedure from the program status data structure in the RPG program. It may seem redundant to use this keyword in both formats, but it really isn't. Specifying this keyword in the subfile record format allows you to link the subfile to a specific program message queue, which then allows you to clear and possibly load the subfile by controlling the program message queue. However, it is the SFLPGMQ keyword entry in the subfile control format that allows you to automatically load the subfile. If you don't specify it in the subfile control format, you will need to code the load routine in your program. Always use this keyword in subfile control format. This is one case in which redundancy causes efficiency.

The RPG

The RPG, SFLMSGRG, is basically used to control SCREEN1. It doesn't have any direct contact with the message subfile. The RPG program will send messages to, and remove messages from, the program message queue and help the message subfile link to the program message queue by retrieving the message queue name from the program data structure and sharing it the display file. But, as you will soon see, it doesn't directly load, clear, or display the subfile.

The program status data structure provides information about the program, just as a file information data structure provides information about a specific file. In my example, I want to retrieve the procedure name associated with this program, which I can get by specifying the keyword *PROC. I will the define SDS_PROC to associate with the *PROC keyword. Notice that this is the same name I used in my DDS. That way, I can pass the name of the procedure, and subsequently the program message queue name, to the display file and allow it to link the program message queue to the message subfile. I also specified the program name, which can be retrieved from positions 334 through 343. I am not going to use that field in my example, but I thought I would show you it's there for your convenience, should you choose to use it.

The mainline of the RPG is simply a DOU loop that processes SCREEN1. Before SCREEN1 is written to allow the user to enter some data, I perform a WRITE to the message subfile control format, MSGCTL. This write causes the message subfile to be loaded with any messages in the program message queue and then be displayed on the screen. The first time through, I haven't sent any messages to the program message queue, so the message subfile is empty.

The initial screen allows the user to enter a first and last name. Once the Enter key is pressed, the RPG program is going to interrogate the names and determine whether a message should be sent. In my example, if the user doesn't enter Kevin as the first name message ID, SFL0001 is moved to the msgID field and the SNDMSG subroutine is executed. If Vandever isn't entered as the last name, msgID is evaluated to SFL0002 and SNDMSG is executed again

Each time the SNDMSG subroutine is executed, a message is written to the program message queue and displayed to the screen when the WRITE operation is performed. Since I want the messages removed after they have been displayed, the first thing I do upon returning from SCREEN1 is to execute the RMVMSG subroutine. This clears the program message queue, and subsequently the message subfile, for the next interrogation of data.

If the user were to spell both names incorrectly (how dare he), two messages would be written to the program message queue. Now when the message subfile is displayed on the screen, you will see the first message with a plus sign (+) on the far right-hand sign, signifying more records. If you place your cursor on the subfile record and press the Page Down key to get the next record, you would see the second error message.

If you are using a message file and added second-level help for your messages, you can see those second-level messages by placing the cursor on the message subfile record and pressing the Help key. You can search all day for the extra code I left out of this program to allow this feature, but you won't find it. That's because it's taken care of for you by OS/400. I think you should take a moment now to thank OS/400 and message subfiles for making your life so much easier.

A Powerful Combination

This technique provides you with a lot of options. Download the code, create a message file and add some messages, and give the example a try. You may also want to further investigate the message APIs. Due space constraints, I did not cover them fully in this article, but they are pretty self-explanatory and easy to use. Using the program message queue to communicate information to the user provides you much flexibility. Add the wizardry of message subfiles, and you're on your way toward creating a killer application--and you haven't even started coding the business logic.


Sponsored By
T.L. ASHFORD

T.L. Ashford's BARCODE400 software makes bar code labeling easy. The software prints labels directly from the iSeries / AS/400 without middleware. Buttons and simple mouse clicks perform most design operations such as placing logos, symbologies text and boxes. You will be designing and printing labels in minutes.

Barcode400 is backed by the best Technical Support Team in the industry.

  • Easily integrate with existing applications
  • Compliance labels available no charge (including the GM1724)
  • FREE Guide to Bar Code Labeling

www.tlashford.com or call 800.541.4893.


THIS ISSUE
SPONSORED BY:

T.L. Ashford
Aldon Computer Group
LANSA
ASNA
Profound Logic Software
WorksRight Software


BACK ISSUES

TABLE OF CONTENTS
Back To Basics: Message Subfiles

The 5250 Word Wrap Utility

Cool Things in CODE/400: A Bag Full of Tips

The Opportunity of a Lifetime

Security Made Easy with Operations Navigator

More on XLE and XML File Creation


Editors
Shannon O'Donnell
Kevin Vandever

Managing Editor
Shannon Pastore

Contributing Editors
Howard Arner
Joe Hertvik
Ted Holt
David Morris
Richard Shaler

Publisher and
Advertising Director

Jenny Thomas

Contact the Editors
Do you have a gripe, inside dope or an opinion?
Email the editors:
editors@itjungle.com



Last Updated: 8/29/02
Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.