Exception handling

An error may occur when an EGL-generated program acts as follows:

try blocks

An EGL try block is a series of zero to many EGL statements within the delimiters try and end. An example is as follows:
  if (userRequest = "A")
    try
      add record1;
    onException
      myErrorHandler(12);
    end
  end

In general, a try block allows your program to continue processing even if an error occurs.

The try block may include an onException clause, as shown earlier. That clause is invoked if one of the earlier statements in the try block fails; but in the absence of an onException clause, an error in a try block causes invocation of the first statement that immediately follows the try block.

System exceptions

EGL provides a series of system exceptions to indicate the specific nature of a runtime problem. Each of these exceptions is a dictionary from which you can retrieve information, but your retrieval is always by way of the system variable SysLib.currentException (also a dictionary), which lets you access the exception thrown most recently in the run unit.

One field in any exception is code, which is a string that identifies the exception. You can determine the current exception by testing that field in logic like this:
  if (userRequest = "A")
    try
      add record1;
    onException
      case (SysLib.currentException.code)
        when (FileIOException)
          myErrorHandler(12);
        otherwise
          myErrorHandler(15);
      end
    end
  end

In this case, FileIOException is a constant, which is equivalent to the string value "com.ibm.egl.FileIOException". The EGL exception constant is always equivalent to the last qualifier in a string that begins "com.ibm.egl".

It is strongly recommended that you access the exception fields only in an onException block. The run unit terminates if your code accesses SysLib.currentException when no exception has occurred.

The next example accesses the field sqlcode in the exception SQLException:
  if (userRequest = "A")
    try
      add record01;
    onException
      case (SysLib.currentException.code)
        when ("com.ibm.egl.SQLException")
          if (SysLib.currentException.sqlcode == -270)
            myErrorHandler(16);
          else
            myErrorHandler(20);
          end
        otherwise
          myErrorHandler(15);
      end
    end
  end

For details on the system exceptions, see EGL system exceptions.

Limits of try blocks

The previous details on try blocks must be qualified. First, a try block affects processing only for errors in the following kinds of EGL statements:
  • An I/O statement
  • A system function
  • A call statement

Processing of numeric overflows is not affected by the presence of a try block. For details on those kinds of error, see VGVar.handleOverflow.

Second, a try block has no effect on errors inside a user function (or program) that is invoked from within the try block. In the next example, if a statement fails in function myABC, the program ends immediately with an error message unless function myABC itself handles the error:
  if (userRequest = "B")
    try
      myVariable = myABC();
    onException
      myErrorHandler(12);
    end
  end
Third, the program ends immediately and with an error message in the following cases:
  • An error of a kind that is covered specifically by a try block occurs outside of a try block; or
  • One of the following cases applies, even in a try block--
    • A user-written function fails at invocation or on return to the invoker; or
    • The system variable VGVar.handleHardIOErrors is set to zero when a file or MQSeries® I/O statement ends with a hard error (as described later); or
    • The system variable DLIVar.handleHardDLIErrors and VGVar.handleHardIOErrors are both set to zero when an attempt to access an IMS™ queue or DL/I database ends with a hard error.
The following cases are also of interest:
  • If a value is divided by zero, a Java™ program handles the situation as a numeric overflow
  • A Java program ends if a non-numeric character is assigned to a numeric variable
Note: To support the migration of programs written in VisualAge® Generator and EGL 5.0, the variable VGVar.handleSysLibraryErrors (previously called ezereply) allows you to process some errors that occur outside of a try block. Avoid use of that variable, which is available only if you are working in VisualAge Generator compatibility mode.

Error-related system variables

EGL provides error-related system variables that are set in a try block either in response to successful events or in response to non-terminating errors. The values in those variables are available in the try block and in code that runs subsequent to the try block, and the values in most cases are restored after a converse, if any.

Within a try block, the following rules apply:
  • The system variable sysVar.errorCode is given a value after any of the following kinds of statements run:
    • A call statement
    • An I/O statement that operates on an indexed, MQ, relative, or serial file
    • An invocation of almost any system function
  • After an I/O statement operates on an MQ record, the system variables sysVar.errorCode and VGVar.mqConditionCode are given values
  • After a relational database is accessed in a try block, values are assigned to variables in the SQL communication area (SQLCA); for details, see SysVar.sqlca
  • After a DL/I database is accessed, values are assigned to the PCB status variables (DLIVar.dbName, DLIVar.keyArea, DLIVar.keyAreaLen, DLIVar.segmentLevel, DLIVar.procOptions, DLIVar.segmentName, DLIVar.numSensitiveSegs, and DLIVar.statusCode).

    If you are running in CICS®, values are also assigned to the CICS DL/I status variables (DLIVar.cicsError, DLIVar.cicsCondition, and DLIVar.cicsRestart).

EGL runtime does not set the DL/I-related variables listed earlier after your code accesses a GSAM file or an IMS message queue access. That access is considered to be serial-file access. To gain access to additional status information in those cases, use the appropriate PCB record. For an overview, see EGL support for runtime PSBs and PCBs. For details on particular types of PCB records, see Record types and properties.

An error code is assigned to sysVar.errorCode in the case of a non-terminating numeric overflow, as described in VGVar.handleOverflow; but a successful arithmetic calculation does not affect any error-related system variable.

Error-related system variables are also not affected by the invocation of a function other than a system function, and sysVar.errorCode (the variable affected by most system functions) is not affected by errors in these:
  • sysLib.calculateChkDigitMod10
  • sysLib.calculateChkDigitMod11
  • strLib.concatenate
  • strLib.concatenateWithSeparator
  • VGLib.concatenateBytes
  • VGLib.connectionService
  • sysLib.connect
  • sysLib.convert
  • sysLib.disconnect
  • sysLib.disconnectAll
  • sysLib.purge
  • sysLib.queryCurrentDatabase
  • strLib.setBlankTerminator
  • sysLib.setCurrentDatabase
  • strLib.strLen
  • sysLib.verifyChkDigitMod10
  • sysLib.verifyChkDigitMod11
  • sysLib.wait

The EGL runtime does not change the value of any error-related variables when statements run outside of a try block. Your program, however, may assign a value to an error-related variable outside of a try block.

I/O statements

In relation to I/O statements, an error can be hard or soft:
  • A soft error is any of these--
    • No record was found during an I/O operation on an SQL database table
    • One of the following problems occurs in an I/O operation on an indexed, relative, or serial file; on a DL/I segment; or in other DL/I access:
      • Duplicate record (when the external data store allows insertion of a duplicate). The equivalent DL/I status code is II.
      • No record found. The equivalent DL/I status code is GE, and the equivalent IMS message-queue status code is QD.
      • End of file. The equivalent DL/I or GSAM status code is GB, and the equivalent IMS message-queue status code is QC,
  • In most cases, a hard error is any other problem; for example--
    • Duplicate record (when the external data store prohibits insertion of a duplicate)
    • File not found
    • Communication links are not available during remote access of a data set

    In relation to DL/I, a hard error is any non-blank status code other than GA, GB, GD, GE,GK, or II, In relation to GSAM, a hard error is any non-blank status code other than GB. In relation to IMS, a hard error is any non-blank status code other than QC, QD, CE, CF, CG, CI, CJ, CK, or CL.

If the statement that causes the soft error is in a try block, the following statements apply:
  • By default, EGL continues running without passing control to the onException block
  • If you wish to pass control to the OnException block, set the property throwNrfEofExceptions to yes in a program, pageHandler, or library
If a hard I/O error occurs in a try block, the consequence depends on the value of an error-related system variable:
  • During access of a file, relational database, or MQSeries message queue, the following rules apply--
    • If sysVar.handleHardIOErrors is set to 1, the program continues running
    • If sysVar.handleHardIOErrors is set to 0, the program presents an error message, if possible, and ends

    The default setting of that variable is dependent on the value of the property handleHardIOErrors , which is available in generatable logic parts like programs, libraries, and pageHandlers. The default value for the property is yes, which sets the initial value of the variable sysVar.handleHardIOErrors to 1.

  • During access of an IMS queue or DL/I database, the following rules apply--
    • If VGVar.handleHardIOErrors or DLIVar.handleHardDLIErrors is set to 1, the program continues running
    • If VGVar.handleHardIOErrors or DLIVar.handleHardDLIErrors is set to 0, the program presents an error message, if possible, and ends

If either a hard or soft I/O error occurs outside of a try block, the generated program presents an error message, if possible, and ends.

If you are accessing DB2® directly (not through JDBC), the sqlcode for a hard error is 304, 802, or less than 0.

Error identification

You can determine what kind of error occurred in a try block by including a case or if statement inside or outside the try block, and in that statement you can test the value of various system variables. If you are responding to an I/O error and if your statement uses an EGL record, however, it is recommended that you use an elementary logical expression. Two formats of the expression are available:
  recordName is IOerrorValue

  recordName not IOerrorValue
recordName
Name of the record used in the I/O operation
IOerrorValue
One of several I/O error values that are constant across database management systems

If you don't use the logical expressions with I/O error values and then change database management systems, you may need to modify and regenerate your program. In particular, it is recommended that you use the I/O error values to test for errors rather than the value of sysVar.sqlcode or sysVar.sqlState. Those values are dependent on the underlying database implementation.

Feedback
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.