This example expects errors to be sent as escape messages.
In the following program example, all the pieces have been put together with an RPG program that accesses the hold on job queue information from a job description. A message is sent for the value found. To make the RPG program more general purpose, two parameters for the job description (JOBD) name and library (JOBDL) name are passed to it, as shown at (5). The program example, which is named JOBDAPI (this program name is also used in other examples in this chapter), does not handle errors. Any errors that are received are returned as exception messages.
I***************************************************************** I***************************************************************** I* I*Program Name: JOBDAPI I* I*Language: OPM RPG I* I*Descriptive Name: Job Description I* I*Description: This example expects errors to be sent as escape I* messages. I* I*Header Files Included: QUSEC - Error Code Parameter I* QWDRJOBD - Retrieve Job Description API I* I***************************************************************** I***************************************************************** I* I* Error Code Parameter Include for the APIs I* I/COPY QSYSINC/QRPGSRC,QUSEC I* I* Retrieve Job Description API Include I* I/COPY QSYSINC/QRPGSRC,QWDRJOBD (1) I* I* Command String Data Structure I* ICMDSTR DS I I 'SNDMSG MSG(''HOLD - 1 26 CMD1 I 'value is ' I 27 36 HOLD I I ''') TOUSR(QPGMR)' 37 51 CMD2 I* I* Miscellaneous Data Structure I* I DS I* (2) I I 390 B 1 40RCVLEN I I 'JOBD0100' 5 12 FORMAT I* (3) C* C* Beginning of Mainline C* C* Two parameters are being passed into this program. C* C *ENTRY PLIST (5) C PARM JOBD 10 C PARM JOBDL 10 C* C* Move the two parameters passed into LFNAM. C* C JOBD CAT JOBDL LFNAM 20 (6) C* Error code bytes provided is set to 0 C* C Z-ADD0 QUSBNB (4) C* C* Instead of specifying 'QWCRJOBD', I could have used the C* constant QWDBGB that was defined in the QWDRJOBD include. C* C CALL 'QWDRJOBD' C PARM QWDBH Receiver Var. C PARM RCVLEN Length RCVVAR C PARM FORMAT Format Name C PARM LFNAM Qual. Job Desc C PARM QUSBN Error Code C* C MOVELQWDBHN HOLD C* C* Let's tell everyone what the hold value was for this jobd. C* C Z-ADD51 LENSTR 155 C CALL 'QCMDEXC' C PARM CMDSTR C PARM LENSTR C* C SETON LR C RETRN C* C* End of MAINLINE C*
The program declares the variables to be used. The QWDBH variable is length 390 as shown by (2).
In the example, the program places a value of JOBD0100 in the format variable. A literal could have been used instead for those languages that support a literal on a call, as shown at (5). The program generates the qualified name of the job description (JOBD) by concatenating the simple name and the library qualifier, as shown at (6). A 20-character variable must be used, and the simple name must begin in byte 1 with the library qualifier in byte 11. Because CAT is used, a simple concatenation of two 10-byte variables occurs so that the names are in the correct place for the LFNAM parameter.
The QWDRJOBD API is called with the correct parameter list. The API uses the parameter list and accesses the job description specified. The API extracts the values from the internal object form and places them in a data structure that matches the JOBD0100 format. The API then returns with the data structure placed in variable QWDBH, which is located in member QWDRJOBD in the QSYSINC library.
The output is similar to the following:
+--------------------------------------------------------------------------------+ | | | | | Display Messages | | | | System: GENSYS90 | | Queue . . . . . : QPGMR Program . . . . : *DSPMSG | | Library . . . : QUSRSYS Library . . . : | | Severity . . . : 00 Delivery . . . : *HOLD | | Type reply (if required), press Enter. | | From . . . : SMITH 07/23/94 10:25:14 | | HOLD value is *NO | | | +--------------------------------------------------------------------------------+
The API does not need to be called each time that you want a separate field because all fields are returned that would fit within the size indicated by the length of receiver variable (RCVLEN) parameter. You can run the program against the QBATCH job description in library QGPL by using the following call statement:
CALL JOBDAPI PARM(QBATCH QGPL)
If QGPL is on the library list, you can run the program against the QBATCH job description by using the following call statement:
CALL JOBDAPI PARM(QBATCH *LIBL)
You can run the program on one of your own job descriptions or on a test job description where you have specified HOLD(*YES).
For this example, assume that the XYZ job description does not exist:
CALL JOBDAPI PARM(XYZ *LIBL)
You probably will receive the inquiry message CPA0701 that states an unmonitored exception (CPF9801) has occurred and offers several possible replies. At this point, you would enter C for Cancel and press the Enter key.
If you displayed the low-level messages, you would see the following: CPF9801 (Object not found), followed by the inquiry message (CPA0701), followed by your reply.
When you specify the error code parameter as zero, you are specifying that exceptions be sent as escape messages. You can code the RPG program so that any errors on the call set the indicator 01 to on, as shown at (10). This causes a different path to be taken in the code.
For RPG, the CALL operation specifies the error indicator. Based on whether the error indicator is on or off, a set of instructions can be processed. The API must receive an error code parameter that consists of a binary 4 field with a value of binary zeros, as shown at (11)). The message ID can be accessed from the program-status data structure. You would define this as follows:
I* Program status DS ((12)) IPGMSTS SDS I 40 46 MSGIDD
If you are going to do something about an error condition, you must test for an error condition in RPG:
Because you must test for some condition (one of the error messages in Error Messages), no great difference exists in how you handle error conditions in RPG. The error-code data structure is a little more straightforward (the program-status data structure is not used). The only disadvantage of the error-code data structure is that the escape message that occurred was removed from the job log.
The following program shows how to code for an error condition, test for that condition, and send a message to the QPGMR message queue if the condition occurs:
I***************************************************************** I***************************************************************** I* I*Program Name: JOBDAPI I* I*Language: OPM RPG I* I*Descriptive Name: Get Job Description I* I*Description: This program handles any errors that are I* returned I* I*Header Files Included: QUSEC - Error Code Parameter I* QWDRJOBD - Retrieve Job Description API I* I***************************************************************** I***************************************************************** I* I* Error Code Parameter Include for the APIs I* I/COPY QSYSINC/QRPGSRC,QUSEC I* I* Retrieve Job Description API Include I* I/COPY QSYSINC/QRPGSRC,QWDRJOBD I* Program status DS IPGMSTS SDS (12) I 40 46 MSGIDD I* I* Command String Data Structure I* ICMDSTR DS I I 'SNDMSG MSG(''HOLD - 1 26 CMD1 I 'value is ' I 27 36 HOLD I I ''') TOUSR(QPGMR)' 37 51 CMD2 I* IMSG3 DS I I 'SNDMSG MSG(''No such- 1 35 MSG3A I ' *JOBD exists'') ' I I 'TOUSR(QPGMR)' 36 47 MSG3B I* I* Miscellaneous Data Structure I* I DS I I 390 B 1 40RCVLEN I I 'JOBD0100' 5 12 FORMAT C* C* Beginning of Mainline C* C* Two parameters are being passed into this program. C* C *ENTRY PLIST C PARM JOBD 10 C PARM JOBDL 10 C* C* Move the two parameters passed into LFNAM. C* C JOBD CAT JOBDL LFNAM 20 C* Error code bytes provided is set to 0 C* C Z-ADD0 QUSBNB (11) C* C* Instead of specifying 'QWCRJOBD', I could have used the C* constant QWDBGB that was defined in the QWDRJOBD include. C* C CALL 'QWDRJOBD' 01 (10) C PARM QWDBH Receiver Var. C PARM RCVLEN Length RCVVAR C PARM FORMAT Format Name C PARM LFNAM Qual. Job Desc C PARM QUSBN Error Code C 01 EXSR ERROR Error Subroutine C* C N01 MOVELQWDBHN HOLD C* C* Let's tell everyone what the hold value was for this job. C* C N01 Z-ADD51 LENSTR 155 C N01 CALL 'QCMDEXC' C PARM CMDSTR C PARM LENSTR C* C SETON LR C RETRN C* C* End of MAINLINE C* C* Subroutine to handle errors received on the CALL C* C ERROR BEGSR C MSGIDD IFEQ 'CPF9801' C* C* Process errors returned from the API. C* C Z-ADD47 LENSTR 155 C CALL 'QCMDEXC' C PARM MSG3 C PARM LENSTR C END C ENDSR
If the CPF9801 exception occurs, your program sends a message to the QPGMR message queue as shown in the following display:
+--------------------------------------------------------------------------------+ | | | | | Display Messages | | | | | | System: GENSYS90 | | Queue . . . . . : QPGMR Program . . . . : *DSPMSG | | Library . . . : QUSRSYS Library . . . : | | Severity . . . : 00 Delivery . . . : *HOLD | | Type reply (if required), press Enter. | | From . . . : SMITH 07/25/94 11:10:12 | | No such *JOBD exists | | | +--------------------------------------------------------------------------------+
If another exception occurs (for example, a library name that is not valid), you do not receive an indication that an error occurred because of the way the error subroutine is currently coded.
In addition, you can use the Message Handling APIs to receive the messages sent to your program message queue.
The call to the API fails if you specify a valid job description but use a library qualifier such as *ALLUSR. The value *ALLUSR is not supported by the description of the required parameter group.
See the following for the same example in different languages: