The occurrence of an exception is normally used to display an error situation. The handler of an exception must try to correct the error that has occurred, find an alternative solution, or (if this is not possible) at least bring the affected context into a consistent state and then forward the error. If a call hierarchy does not contain a handler for an exception, the program is ended with a runtime error. Since exceptions cannot be handled by means of program calls, all possible exceptions within the program itself must be handled to prevent a runtime error. This rule does not apply to the coding within procedures whose exceptions can easily be propagated to (external) callers.
Class-based exceptions are handled in the following control structure:
..." TRY block (application coding)
CATCH cx_... cx_... ...
..." CATCH block (exception handler)
CATCH cx_... cx_... ...
..." CATCH block (exception handler)
..." CLEANUP block (cleanup context)
The TRY statement opens a control structure to be ended with ENDTRY, in which three statement blocks can be listed in a specified order (this is not obligatory).
Like all ABAP control structures, TRY-ENDTRY structures can be nested in any statement blocks (seeControlling the Program Flow). In particular, the three statements blocks above can also contain complete TRY-ENDTRY blocks. Like all ABAP control structures, each TRY-ENDTRY structure must be contained fully in a processing block (event block, dialog module, procedure). This means that the application coding of a TRY-ENDTRY structure cannot include several processing blocks.
The TRY block contains the application coding whose exceptions are to be handled. This statement block is processed sequentially. It can contain further control structures and calls of procedures or other ABAP programs.
If an exception occurs in the TRY block or in a procedure called up here, the system starts by searching for a CATCH statement of the same TRY-ENDTRY structure. It then searches from the inside out for a CATCH statement in any enclosing TRY-ENDTRY structures that handle the event. The system may call this handler. If the system does not find a handler, but the TRY-ENDTRY structure is contained in a procedure, it tries to propagate the exception to the caller (see alsoPropagating Exceptions). Exceptions cannot be propagated in any processing blocks without a local data area (event blocks, dialog modules). A runtime error occurs immediately if the handler is missing.
If no exceptions occur in the TRY block, program execution is continued directly after ENDTRY after the block has been completed.
A catch block contains the exception handler that is executed when a particular exception has occurred in the TRY block of the same TRY-ENDTRY structure. A TRY-ENDTRY structure can contain several exception handlers. The syntax for introducing an exception handler is:
CATCH cx_... cx_... INTO ref.
Any number of exception classes can be specified after CATCH. This defines an exception handler for all the specified exception classes and their subordinate classes.
After an exception occurs, the system searches through the listed exception handlers in the specified order. The first exception handler whose CATCH statement contains the corresponding exception class or one of its superclasses is executed. The system then continues program execution directly after ENDTRY. No subsequent exception handlers are considered. For this reason, the order of the different exception handlers within a TRY-ENDTRY structure must be based on the inheritance hierarchy of the specified exception classes.
The syntax check ensures that the handlers for more specific exceptions (subordinate classes) can only be listed before the handlers for more general exceptions (superclasses). For example, a handler for the most general exception class CX_ROOT can only ever be the last statement block before CLEANUP or ENTRY. Otherwise, none of the subsequent handlers would ever be reached.
With the INTO addition, a reference to the exception object can be placed a reference variable. This enables the attributes of the exception object to be accessed in the handler. The reference variable must be suitable for the exception. Its static type must be the exception class itself or one of its superclasses. You are advised to use an exception class below CX_ROOT or CX_ROOT itself rather than the general class OBJECT. Only these classes contain the methods relevant for exceptions.
If the system does not find a handler for an exception in a TRY-ENDTRY structure, it searches for a handler in the enclosing TRY-ENDTRY structures from the inside out (as mentioned above). If the system does not find a handler here, it tries to propagate the exception to a procedure caller.
Precisely one CLEANUP block can be defined in each TRY-ENDTRY structure. If the system has not found a handler for an exception, but the exception is handled in an enclosing TRY-ENDTRY structure or is propagated to a caller, the block is executed before the TRY-ENDTRY structure is exited.
In the CLEANUP block, cleanup work can be executed for the context of the TRY block. For example, objects often have to be brought into a consistent state or external resources, to which an external handler no longer has access, have to be released. The nesting of TRY-ENDTRY blocks and the possible propagation of exceptions may mean that several CLEANUP blocks are executed before an exception is actually handled.
Since the only purpose of the CLEANUP block is to restore the consistency of a context, it can only be exited in the normal way, in other words, once its last statement is reached. For this reason, all the statements that change the control flow, which cause the CLEANUP block to be exited and would initiate a processing block of the same program, are forbidden. This applies to statements such as RETURN, STOP, for example. For the same reason, all the exceptions that occur within a CLEANUP block must also be handled here. It is, however, permissible to leave the overall program (LEAVE PROGRAM) or call up procedures, programs, and screen sequences if the system returns to the CLEANUP block. The runtime environment always recognizes that a CLEANUP block is being exited illegally and then reacts with a runtime error.
parameters NUMBER type I.
data RESULT type P decimals 2.
data OREF type ref to CX_ROOT.
data TEXT type STRING.
write: / 'Testing division and Sqare root with', NUMBER.
In this example, a TRY-ENDTRY structure is nested in the TRY block of a different TRY-ENDTRY structure. The following four scenarios are demonstrated in the example:
Catching an Exception by Handling a Superclass
If NUMBER is greater than 100, the exception CX_DEMO_ABS_TOO_LARGE that is self-defined in theException Builder of the ABAP Workbench is raised in the TRY block of the external TRY-ENDTRY structure. This exception is the subordinate class of the most general exception, CX_ROOT, and is handled by the second CATCH block of the same TRY-ENDTRY structure.
Catching an Exception by Handling the Suitable Class
If NUMBER is equal to zero, the exception CX_SY_ZERODIVIDE predefined in the system is raised as a result of the division in the TRY block of the internal TRY-ENDTRY structure and handled in the corresponding CATCH block of the same TRY-ENDTRY structure.
Executing a CLEANUP Block Before Catching an Exception
If NUMBER is a negative number, the exception CX_SY_ARG_OUT_OF_DOMAIN predefined in the system is raised in the TRY block of the internal TRY-ENDTRY structure using the SQRT function. Since a handler is not defined for this exception in the internal TRY-ENDTRY structure but is defined in the external TRY-ENDTRY structure, the CLEANUP block of the internal TRY-ENDTRY structure is executed. The exception is then handled in the first CATCH block of the external TRY-ENDTRY structure, since CX_SY_ARG_OUT_OF_DOMAIN is the subordinate class of CX_SY_ARITHMETIC_ERROR.
In all other cases, an exception is not raised and the TRY blocks of both TRY-ENDTRY structures are fully processed.
In all CATCH statements in the example, the object references to the corresponding exception objects are stored in the OREF reference variable. Using OREF, the individual handlers access the exception texts of the individual exception objects and store them in the TEXT string variable.