The API Corner: Sending Non-Error-Related Messages from an Application Program PDF Print E-mail
Programming - APIs
Written by Bruce Vining   
Tuesday, 16 March 2010 23:00

Support MC Press - Visit Our Sponsors

 

Forums Sponsor

POPULAR FORUMS
  1. News on IFSTOOL (2565 views)
  2. AS/400 RPG Programmer Analyst - Tampa, FL (Contract) (2134 views)
  3. I need to transfer a spool file(i.e. compile listing) to a PC file for editing (1872 views)
  4. Latest news on HSSFCGI (1682 views)
  5. Batch file in as400 (1473 views)
  6. Trigger bombing on program library (1230 views)
  7. Zip/Unzip now, don't wait for 7.1 (883 views)
  8. PHFA - 2 new Software Developer positions available (IBM i RPG ILE/Microsoft Dotnet) (530 views)
  9. The International Freedom of Expression Forum (501 views)
  10. A6005004 - Can't find console (350 views)

Forums

 

Search Sponsor

Search

 


Sometimes you want to see messages that tell you things went right instead of wrong.

 

In the previous article, "More On Sending Messages from an Application Program", the Send Program Message (QMHSNDPM) API was used to send a user error message indicating that a severe error had been encountered and, if appropriate, diagnostic messages explaining the cause of the error. But not all programs encounter problems—at least I hope not all of your programs do! In this article, the QMHSNDPM API will also be used, but now to send a variety of non-error related messages.

 

We'll start with a simple completion message indicating that some function of the application has successfully finished. Similar to how message descriptions APP0001 and APP0002 were used in previous articles, create the new message APP0003 using this command:

 

ADDMSGD MSGID(APP0003) MSGF(QGPL/APPLMSGF) +

   MSG('Task finished successfully.')

 

The message text for APP0003 is vaguer than I would recommend, but as I do not intend to write a full application, with specific functional tasks, as part of this article, it is sufficient for now. For any application programs you write in the future, I'm sure you can come up with more meaningful message text—for instance, "Customer &1 added," or "Month-end balancing successful," or the like.

 

To send message APP0003 to the programs caller, we will use the same Send Program Message (QMHSNDPM) API as in previous articles. Here's the code to do this:

 

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')      

d MsgID                          7    const                        

d QualMsgF                      20    const                        

d MsgDta                     65535    const options(*varsize)      

d LenMsgDta                     10i 0 const                         

d MsgType                       10    const                        

d CallStackEntry             65535    const options(*varsize)      

d CallStackCntr                 10i 0 const                        

d MsgKey                         4                                  

d QUSEC                               likeds(QUSEC)                

d LenCSE                        10i 0 const options(*nopass)       

d CSEQual                       20    const options(*nopass)       

d DSPWaitTime                   10i 0 const options(*nopass)       

d CSEType                       10    const options(*nopass)       

d CCSID                         10i 0 const options(*nopass)       

                                                                   

 /copy qsysinc/qrpglesrc,qusec                           

                                                         

dMsgFName         ds                                     

d Name                          10    inz('APPLMSGF')    

d Lib                           10    inz('QGPL')        

                                                         

dMsgKey           s              4                       

                                                         

 /free                                                    

                                                         

  QUSBPRV = 0;                                           

                                                         

  SndMsg( 'APP0003' :MsgFName :' ' :0 :'*COMP'           

         :'*PGMBDY' :1 :MsgKey :QUSEC);                  

                                                         

  *inlr = *on;                                           

  return;                                                

                        

 /end-free             

 

Let's say that the previous source is stored in member SNDAPP0003 of source file QRPGLESRC. The following commands can be used to create and then call the program.

 

CRTBNDRPG PGM(SNDAPP0003)

CALL PGM(SNDAPP0003)

 

Assuming these commands are done from QCMD, you will now see the message "Task finished successfully." If you are not calling SNDAPP0003 from a command line, you may need to display your job log in order to see the message. Not too much of a change in calling the API to start sending messages of a non-error nature! We changed the message type (the fifth parameter when calling the QMHSNDPM API) from *ESCAPE to *COMP (completion) and, as there is no replacement data for message APP0003, also the third and fourth parameters to reflect that no variable data is being provided. If you want to provide variable data in the completion message, you can do so in the same way message IDs APP0001 and APP0002 did in the previous articles (or as will be seen shortly with message APP0004).

 

What if the task associated with message APP0003 is potentially long-running? How might we provide status information to the user, similar to how some long-running system commands such as Copy File (CPYF) do, so that the user doesn't think he's stuck in some problem within the program? As you might expect, we could again use the QMHSNDPM API. Create the new message APP0004 using this command:

 

ADDMSGD MSGID(APP0004) MSGF(QGPL/APPLMSGF) +

   MSG('Step &1 of &2 in progress.') +

   FMT((*UBIN 2) (*UBIN 2))

 

Message APP0004 will be used to provide ongoing status information to the user while the SNDAPP0003 program is running. In our fictitious task, there will be three steps and APP0004 will tell the user what step is currently being performed. When all steps are done, APP0003 will indicate successful completion of the task.

 

APP0004 defines two replacement variables. The first variable, &1, is defined as a 2-byte unsigned integer and represents the current step being performed. The second variable is also defined as a 2-byte unsigned integer and represents the total number of steps to be run.

 

Adding APP0004 support (and a few other items we'll discuss) to the previous SNDAPP0003 program results in the following RPG program:

 

h dftactgrp(*no)                                                  

                                                                 

dSndMsg           pr                  extpgm('QSYS/QMHSNDPM')    

d MsgID                          7    const                      

d QualMsgF                      20    const                      

d MsgDta                     65535    const options(*varsize)    

d LenMsgDta                     10i 0 const                      

d MsgType                       10    const                      

d CallStackEntry             65535    const options(*varsize)    

d CallStackCntr                 10i 0 const                      

d MsgKey                         4                               

d QUSEC                               likeds(QUSEC)               

d LenCSE                        10i 0 const options(*nopass)     

d CSEQual                       20    const options(*nopass)     

d DSPWaitTime                   10i 0 const options(*nopass)     

d CSEType                       10    const options(*nopass)     

d CCSID                         10i 0 const options(*nopass)   

                                                               

dSleep            pr            10u 0 extproc('sleep')         

d Seconds                       10u 0 value                     

                                                               

 /copy qsysinc/qrpglesrc,qusec                                 

                                                               

dMsgFName         ds                                            

d Name                          10    inz('APPLMSGF')          

d Lib                           10    inz('QGPL')              

                                                               

dMsgKey           s              4                              

                                                               

dAPP0004          ds                                           

d Step                           5u 0                          

d Total                          5u 0 inz(3)                   

                                                               

 /free                                                               

                                                                     

  QUSBPRV = 0;                                                        

                                                                     

  for Step = 1 to Total;                                             

      SndMsg( 'APP0004' :MsgFName :APP0004 :%size(APP0004) :'*STATUS'

             :'*EXT' :0 :MsgKey :QUSEC);                             

      Sleep(Step);                                                   

  endfor;                                                            

                                                                      

  SndMsg( 'APP0003' :MsgFName :' ' :0 :'*COMP'                       

         :'*PGMBDY' :1 :MsgKey :QUSEC);                              

                                                                     

  *inlr = *on;                                                       

  return;                                                            

                                                                     

 /end-free                                                            

 

By compiling and again running program SNDAPP0003, you should now see the APP0004 message appear on line 24 of the display, get updated at each step (iteration of the FOR loop) of the program, and finally display the APP0003 message when the program finishes. If you don't see the APP0004 message, then your user profile probably has USROPT(*NOSTSMSG) specified or your job is defined with STSMSG(*NONE).

 

Displaying the status message only required the definition of the APP0004 data structure (to reflect the two replacement data variables) and the additional call to the QMHSNDPM. When calling the API, this version of the program, when contrasted to the sending of message APP0003, references message ID APP0004, uses a sixth parameter value of  *EXT (external message queue), and indicates that the message is of type *STATUS. The other changes to SNDAPP0003 are related to delaying the running of the steps so that you have an opportunity to see the status messages!

 

To give you time to view the status messages, the program uses the sleep API documented here. The sleep API defines one input parameter (the number of seconds to delay the thread) and a return value indicating whether the API returned prior to the requested number of seconds having elapsed. Why the API might return earlier is not relevant to our discussion and will not be discussed further (at least in this article). The SNDAPP0003 program, in order to simulate some processing, essentially sleeps for the number of seconds reflected by the number of the step being run. That is, step one takes one second, step two takes (or sleeps) for two seconds, etc. As sleep is a bound API, SNDAPP0003 also added an H-spec indicating that the default activation group is not being used.

 

One of the nice features of a status message is that the system takes care of displaying the message on line 24. If you run SNDAPP0003 from the command line, you see the APP0004 message. If you were to embed the SNDAPP0003 calling of QMHSNDPM for the sending of status messages within an interactive RPG application using a *DSPF, you would also see the APP0004 message on line 24 of your display file record format—and with no change to the *DSPF required. When the program ends, or other activity is directed to the display device, the status message is gone. And "gone" includes not being in your job log.

 

In this article, you've seen how easy it can be to provide positive feedback to your users. Next month, we will continue our review of message handling on the system.

 

In the meantime, if you have any API questions, send them to me at bvining@brucevining.com. I'll see what I can do about answering your burning questions in future columns.

    


Bruce Vining
About the Author:

Bruce Vining is president and co-founder of Bruce Vining Services, L.L.C., a firm providing contract programming and consulting services to the System i community (www.brucevining.com). He began his career in1979 as an IBM Systems Engineer in St. Louis, Missouri, and then transferred to Rochester, Minnesota, in 1985, where he continues to reside. From 1992 until leaving IBM in 2007, Bruce was a member of the System Design Control Group responsible for OS/400 and i5/OS areas such as System APIs, Globalization, and Software Serviceability. He is also the designer of Control Language for Files (CLF).

 

A frequent speaker and writer, Bruce can be reached at bvining@brucevining.com.

 

MC Press books written by Bruce Vining available now on the MC Press Bookstore.

 

IBM System i APIs at Work IBM System i APIs at Work

Master APIs with this in-depth, example-rich exploration into these powerful tools.

List Price $89.95
Now On Sale
 
Read More >>
Last Updated on Tuesday, 16 March 2010 23:00
 

You must be logged in to view or make comments on this article.


User Rating: / 0
PoorBest 
   MC-STORE.COM