Example in OPM RPG: Retrieving the HOLD parameter (error code structure)

This sample program shows exceptions being returned in the error code parameter.

Note: Read the Code license and disclaimer information for important legal information.

In the Example in OPM RPG: Retrieving the HOLD parameter (exception message), QUSBNB was set to a value of binary zero to tell the API to send exceptions (escape messages) for any error conditions. The example in this topic uses an error-code data structure as an alternative to receiving exceptions.

Some languages do not support the use of exceptions, so you may prefer to code for errors using error code structures.

In your programs, you can use error code structures in the following ways:

Note: Lengths of 1 through 7 bytes are not valid for the error code structure.

Format of an error code structure

The format of the error code structure (QUSBN) is:

Offset Use Type Field
Dec Hex
0 0 INPUT BINARY(4) Bytes provided
4 4 OUTPUT BINARY(4) Bytes available
8 8 OUTPUT CHAR(7) Exception ID
15 F OUTPUT CHAR(1) Reserved
16 10 OUTPUT CHAR(*) Exception data

The error code structure can be found in the QSYSINC library in the member QUSEC, as shown at (1). Which of the files you use depends on the language. For more information on the QSYSINC library, see Include files and the QSYSINC Library.

The bytes provided field describes the size of the error code structure that you declared in your program and how you want errors returned. (This was set to 0 as shown by (6) in Example in OPM RPG: Retrieving the HOLD parameter (exception message).)

The bytes available field describes how many bytes the API could have passed back. If this field is zero, no exception occurred. The correct method for testing if an error occurred when using a nonzero-bytes-provided value is to check this field for a value greater than zero, as shown at (2).

The exception ID is the normal 7-character message ID, such as CPF9801, that occurs for an object-not-found condition. Do not test this field to determine if an error exists. The field is properly set by the system only if the number of bytes available is greater than 0. Similarly, the exception data (message data) information is not set properly unless an error exists; for example, any information left from a prior call is not changed.

The following program is the same as the previous program except that a 16-byte error code structure is used:

     I*****************************************************************
     I*****************************************************************
     I*
     I*Program Name: JOBDAPI
     I*
     I*Language:  OPM RPG
     I*
     I*Descriptive Name:  Get Job Description
     I*
     I*Description: This sample program shows exceptions being
     I*             returned in the error code parameter.
     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                       (1)
     I*
     I* Retrieve Job Description API Include
     I*
     I/COPY QSYSINC/QRPGSRC,QWDRJOBD
     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*
     IMSG2        DS
     I I            'SNDMSG MSG(''Progr-      1  43 MSG2A
     I              'am failed with mes-
     I              'sage ID '
     I                                       44  50 MSGIDD
     I I            ''') TOUSR(QPGMR)'       51  65 MSG2B
     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 the LFNAM.
     C*
     C           JOBD      CAT  JOBDL     LFNAM  20
     C*
     C* Error code parameter is set to 16
     C*
     C                     Z-ADD16        QUSBNB                  (3)
     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* See if any errors were returned in the error code parameter.
     C                     EXSR ERRCOD
     C*
     C*
     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*
     C* Subroutine to handle errors returned in the error code
     C* parameter.
     C*
     C           ERRCOD    BEGSR
     C           QUSBNC    IFGT 0                      (2)
     C*
     C* Process errors returned from the API.
     C*
     C                     SETON                     01
     C                     Z-ADD65        LENSTR 155
     C                     MOVELQUSBND    MSGIDD
     C                     CALL 'QCMDEXC'
     C                     PARM           MSG2
     C                     PARM           LENSTR
     C                     END
     C                     ENDSR

The QUSBN error-code data structure is defined in the include file QUSEC, as shown at (1), and the program initializes the bytes provided field (QUSBNB) with a value of 16, as shown at (3). This sets the first field of the error code structure to tell the API not to send an exception but to use the first 16 bytes of the QUSBN parameter to return the error information. After the CALL to the API, the program accesses the bytes available (QUSBNC), as shown at (2). This contains the number of bytes of information about the error condition. The program is coded so that it tests if the number exceeds zero. This is the correct method of determining whether an error has occurred.

If an error occurred, you may want to handle the error in many different methods. The program shown extracts the specific error message ID that occurred and sends the 7-character value as a message. The QUSBN parameter is used for both input and output (see Format of an error code structure). The first 4 bytes are input to the API to tell it how to handle exceptions. The remaining bytes are output from the API about any exception conditions.

To see the value of the HOLD attribute, use the following call statement to run the program against the QBATCH job description in library QGPL:

CALL JOBDAPI (QBATCH QGPL)

You should see that the value of the HOLD attribute is *NO:

+--------------------------------------------------------------------------------+
|                                                                                |
|                                                                                |
|                                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                                                            |
|                                                                                |
+--------------------------------------------------------------------------------+

Example in OPM RPG: Handling error conditions

For this error condition, you should assume that the XYZ job description does not exist. Use the following call statement to run the error condition:

CALL JOBDAPI (XYZ *LIBL)

You should see that the CPF9801 message (Object not found) was issued:

+--------------------------------------------------------------------------------+
|                                                                                |
|                                                                                |
|                                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:56:13                           |
|   Program failed with message ID CPF9801                                       |
|                                                                                |
|                                                                                |
+--------------------------------------------------------------------------------+

Then run another error condition. For this error condition, you should assume that the XYZ library does not exist. Use the following call statement:

CALL JOBDAPI (QPGMR XYZ)

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:56:13                           |
|   Program failed with message ID CPF9810                                       |
|                                                                                |
+--------------------------------------------------------------------------------+

You should see that the CPF9810 message (Library not found) was issued. An advantage of the error return variable is that it can contain other information such as message data. The following are the changes needed to return a 200-byte error code structure:

     I*****************************************************************
     I*****************************************************************
     I*
     I*Program Name: JOBDAPI
     I*
     I*Language:  OPM RPG
     I*
     I*Descriptive Name:  Get Job Description
     I*
     I*Description: This sample program shows the incorrect
     I*          way of using the offset in a user space in RPG.
     I*
     I*Header Files Included: QUSEC - Error Code Parameter
     I*                               (Copied into Program)
     I*                       QWDRJOBD - Retrieve Job Description API
     I*
     I*****************************************************************
     I* Error Code Parameter Include for the APIs
     I*
     I* The following QUSEC include is copied into this program
     I* so that the variable-length field can be defined as
     I* fixed length.
     I*
     I*** START HEADER FILE SPECIFICATIONS ****************************
     I*
     I*Header File Name: H/QUSEC
     I*
     I*Descriptive Name: Error Code Parameter.
     I*
     I*5763-SS1  (C) Copyright IBM Corp. 1994,1994
     I*All rights reserved.
     I*US Government Users Restricted Rights -
     I*Use, duplication or disclosure restricted
     I*by GSA ADP Schedule Contract with IBM Corp.
     I*
     I*Licensed Materials-Property of IBM
     I*
     I*
     I*Description: Include header file for the error code parameter.
     I*
     I*Header Files Included: None.
     I*
     I*Macros List: None.
     I*
     I*Structure List: Qus_EC_t
     I*
     I*Function Prototype List: None.
     I*
     I*Change Activity:
     I*
     I*CFD List:
     I*
     I*FLAG REASON       LEVEL DATE   PGMR      CHANGE DESCRIPTION
     I*---- ------------ ----- ------ --------- ----------------------
     I*$A0= D2862000     3D10  931201 DPOHLSON: New Include
     I*
     I*End CFD List.
     I*
     I*Additional notes about the Change Activity
     I*End Change Activity.
     I*** END HEADER FILE SPECIFICATIONS ******************************
     I*****************************************************************
     I*Record structure for Error Code Parameter
     I****                                                          ***
     I*NOTE: The following type definition defines only the fixed
     I*   portion of the format.  Varying-length field exception
     I*   data is not defined here.
     I*****************************************************************
     IQUSBN       DS
     I*                                             Qus EC
     I                                    B   1   40QUSBNB
     I*                                             Bytes Provided
     I                                    B   5   80QUSBNC
     I*                                             Bytes Available
     I                                        9  15 QUSBND
     I*                                             Exception Id
     I                                       16  16 QUSBNF
     I*                                             Reserved
     I*                                      17  17 QUSBNG
     I*
     I*                                      Varying length
     I                                       17 200 QUSBNG   (4)

     .
     .
     .

     C                     Z-ADD200       QUSBNB
     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

The value placed in the QUSBNG variable (4) is the message data associated with the message ID that is identified as the exception. The message data follows the same format as if you had entered a Receive Message (RCVMSG) command and requested the message data (MSGDTA) parameter. You can use the Display Message Description (DSPMSGD) command to determine the layout of the message data for a particular message ID. When you handle exceptions, the only information provided is the exception ID and the message data associated with the exception. You cannot receive a diagnostic message (if one were sent in addition to the escape message) in the error-code data structure. You can use the message handling APIs to receive messages from your program message queue and to access the other messages that may be issued from the API.

When you instruct the API to return all errors in the error-code data structure, the escape message does not appear in the job log. The escape message not appearing in the job log is one of the major differences between letting the API return errors in an error-code data structure and letting the API send escape messages. For the error-code data structure, the escape messages have been removed from the job log by the API. If a diagnostic message is sent first, the diagnostic message exists in the job log and can be received.

See the following for the same example in different languages:

Related concepts
Data types
Related reference
Example in OPM RPG: Retrieving the HOLD parameter (exception message)
Error messages
Example in ILE COBOL: Retrieving the HOLD parameter (error code structure)
Example in ILE C: Retrieving the HOLD parameter (error code structure)
Example in ILE RPG: Retrieving the HOLD parameter (error code structure)
Example in OPM RPG: Accessing the HOLD attribute