异常处理

当 EGL 生成的程序执行下列操作时,可能会发生错误:

try 块

EGL try 块可以不包含 EGL 语句也可以是包含多个 EGL 语句的序列,这些 EGL 语句位于定界符 tryend 之间。下面是一个示例:
  if (userRequest = "A")
    try
      add record1;
    onException
      myErrorHandler(12);
    end
      end

通常,try 块允许程序在发生错误的情况下继续进行处理。

try 块可以包含 onException 子句,如上所示。如果 try 块中的其中一个先前语句失败,则将调用该子句;但是,在不存在 onException 子句的情况下,try 块中的错误将导致调用紧跟在 try 块后的第一个语句。

EGL 系统异常

EGL 提供一系列系统异常以指示运行时问题的具体特性。其中每个异常都是一个字典,您可以从中检索信息,但检索总是通过系统变量 SysLib.currentException(也是一个字典)进行的,它允许您访问运行单元中最近抛出的异常。

任何异常中都有一个字段 code,它是标识该异常的字符串。可以通过以下逻辑测试该字段来确定当前异常:
  if (userRequest = "A")
    try
      add record1;
    onException
      case (SysLib.currentException.code)
        when (FileIOException)
          myErrorHandler(12);
        otherwise
          myErrorHandler(15);
      end
      end
    end
  

在此情况下,FileIOException 是常量,它相当于字符串值“com.ibm.egl.FileIOException”。EGL 异常常量总是等同于以“com.ibm.egl”开头的字符串中的最后一个限定符。

强烈建议只访问 onException 块中的异常字段。如果代码在没有发生任何异常的情况下访问 SysLib.currentException,运行单元将终止。

下一个示例访问异常 SQLException 中的字段 sqlcode:
  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
  

有关系统异常的详细信息,请参阅 EGL 系统异常

try 块的限制

必须符合有关 try 块的先前详细信息。首先,try 块只影响下列类型的 EGL 语句的错误处理:
  • I/O 语句
  • 系统函数
  • call 语句

是否存在 try 块并不影响数字溢出处理。有关这些类型的错误的详细信息,请参阅 VGVar.handleOverflow

其次,try 块对从该 try 块中调用的用户函数(或程序)内的错误不起作用。在下面的示例中,如果函数 myABC 中的语句失败,则除非函数 myABC 本身处理该错误,否则程序将立即结束并发出错误消息:
  if (userRequest = "B")
    try
      myVariable = myABC();
    onException
      myErrorHandler(12);
    end
      end
再次,在下列情况下,程序将立即结束并发出错误消息:
  • 由某一 try 块专门处理的一类错误发生在该 try 块外部;或者
  • 存在下列其中一种情况,甚至是在 try 块中:
    • 在调用或返回用户编写的函数时失败;或者
    • 将非数字字符赋给数字变量;或者
    • 当文件 I/O 语句由于硬错误而结束时,系统变量 VGVar.handleHardIOErrors 被设置为 0 而不是 1(如后文所述)。
下列情况也很重要:
  • 如果某个值除以零,则 Java™ 程序将这种情况作为数字溢出来处理
  • 如果将非数字字符赋值给数字变量,则 Java 程序将结束
注: 为了支持迁移用 VisualAge® Generator 和 EGL 5.0 编写的程序,变量 VGVar.handleSysLibraryErrors(以前称为 ezereply)允许处理一些在 try 块之外发生的错误。避免使用该变量,仅当您以 VisualAge Generator 兼容性方式工作时该变量才可用。

与错误相关的系统变量

EGL 提供了与错误相关的系统变量,在 try 块中设置这些变量以作为对成功事件的响应或对非终止错误的响应。在 try 块中以及在跟在 try 块后面运行的代码中可以使用那些变量的值,在大多数情况下,在转换(如果有的话)之后会恢复那些值。

当语句在 try 块外部运行时,EGL 运行时不更改任何与错误相关的变量的值。但是,程序可以在 try 块外部对与错误相关的变量赋值。

将在各种情况下对系统变量 sysVar.exceptionCode 赋值,在所有那些情况下,还将设置一个或多个其它变量,这取决于程序与运行时环境进行的交互的性质:
  • 在 try 块中运行任何下列类型的语句之后,将对系统变量 sysVar.exceptionCodesysVar.errorCode 赋值:
    • call 语句
    • 对索引文件、MQ 文件、相对文件或串行文件操作的 I/O 语句
    • 对几乎任何系统函数的调用
  • 在 try 块中的 I/O 语句对 MQ 记录执行操作之后,将对系统变量 sysVar.exceptionCodesysVar.errorCodeVGVar.mqConditionCodesysVar.mqReasonCode 赋值
  • 在从 try 块中的语句中访问关系数据库之后,将对系统变量 sysVar.exceptionCode 赋值。还将对 SQL 通信区(SQLCA)中的变量赋值;有关详细信息,请参阅 sysVar.sqlca

如果在 try 块中发生非终止错误,则 sysVar.exceptionCode 的值等同于当在 try 块外部发生错误时将向用户显示的 EGL 错误消息的数字组件。但是,特定于情况的变量(如 sysVar.errorCodeVGVar.mqConditionCode)的值是由运行时系统提供的。未发生错误时,sysVar.exceptionCode 的值与至少一个特定于情况的变量相同:8 个零的字符串。

发生非终止数字溢出时,将会把错误代码赋给 sysVar.exceptionCodesysVar.errorCode,如 VGVar.handleOverflow 所述;但是,成功的算术计算不影响任何与错误相关的系统变量。

与错误相关的系统变量也不受除系统函数外的函数调用的影响,并且,下列各项中的错误不影响 sysVar.errorCode(这是一个受大多数系统函数影响的变量):
  • sysLib.calculateChkDigitMod10
  • sysLib.calculateChkDigitMod11
  • strLib.concatenate
  • strLib.concatenateWithSeparator
  • 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

当将错误值赋给 sysVar.exceptionCode 时,将把相关 EGL 错误消息的文本赋给系统变量 sysVar.exceptionMsg,并将错误消息中的字节数(不包括结尾空格和 NULL)赋给系统变量 sysVar.exceptionMsgCount。在将 8 个零的字符串赋给 sysVar.exceptionCode 时,将把空白赋给 sysVar.exceptionMsg,并将把 sysVar.exceptionMsgCount 设置为 0。

I/O 语句

对于 I/O 语句,可以出现硬错误也可以出现软错误:
  • 软错误是下列任何一项:
    • 在对 SQL 数据库表执行 I/O 操作期间找不到记录
    • 在对索引文件、相对文件或串行文件执行 I/O 操作时发生下列其中一个问题:
      • 记录重复(当外部数据存储允许插入重复记录时)
      • 找不到任何记录
      • 文件结束
  • 硬错误就是任何其它问题;例如:
    • 记录重复(当外部数据存储禁止插入重复记录时)
    • 找不到文件
    • 通信链路在数据集远程访问期间不可用
如果导致软错误的语句在 try 块中,则下列陈述适用:
  • 在缺省情况下,EGL 继续运行并且不会将控制权转交给 onException 块
  • 如果希望将控制权转交给 OnException 块,则在程序、pageHandler 或库中将属性 throwNrfEofExceptions 设置为 yes
如果在 try 块中发生硬 I/O 错误,则后果取决于与错误相关的系统变量的值:
  • 在访问文件、关系数据库或 MQSeries® 消息队列期间,下列规则适用:
    • 如果 VGVar.handleHardIOErrors 设置为 1,则程序继续运行
    • 如果 VGVar.handleHardIOErrors 设置为 0,则程序显示错误消息(如果有可能的话)并结束

    该变量的缺省设置取决于属性 handleHardIOErrors 的值,该属性在可生成逻辑部件(如程序、库和 pageHandler)中可用。该属性的缺省值为 yes,它将变量 VGVar.handleHardIOErrors 的初始值设置为 1。

如果在 try 块外部发生硬 I/O 错误或软 I/O 错误,则生成的程序显示错误消息(如果有可能的话)并结束。

如果正在直接访问 DB2®(而不是通过 JDBC 进行访问),则硬错误的 sqlcode 是 304、802 或小于 0。

错误标识

通过在 try 块内部或外部包括 caseif 语句,可以确定在 try 块中发生的错误的类型,并且可以在该语句中测试各种系统变量的值。但是,如果您正在响应 I/O 错误并且如果语句使用 EGL 记录,则建议您使用基本逻辑表达式。有两种表达式格式:
  recordName is IOerrorValue

  recordName not IOerrorValue
recordName
在 I/O 操作中使用的记录的名称
IOerrorValue
多个 I/O 错误值的其中一个,这些错误值在不同数据库管理系统之间是固定不变的

如果不将逻辑表达式与 I/O 错误值配合使用而后更改数据库管理系统,则可能需要修改并重新生成程序。尤其是,建议您使用 I/O 错误值来测试错误,而不是使用 sysVar.sqlcodesysVar.sqlState 的值。那些值取决于底层数据库实现。

使用条款 | 反馈
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.