Creating user-defined exception types

You can create your own user-defined exception types from standard class user objects that inherit from Exception or RuntimeError or that inherit from an existing user object deriving from Exception or RuntimeError.

Inherit from Exception object type

Normally, user-defined exception types should inherit from the Exception type or a descendant, since the RuntimeError type is used to indicate system errors. These user-defined objects are no different from any other nonvisual user object in the system. They can contain events, functions, and instance variables.

This is useful, for example, in cases where a specific condition, such as the failure of a business rule, might cause application logic to fail. If you create a user-defined exception type to describe such a condition and then catch and handle the exception appropriately, you can prevent a runtime error.

Throwing exceptions

Exceptions can be thrown by the runtime engine to indicate an error condition. If you want to signal a potential exception condition manually, you must use the THROW statement.

Typically, the THROW statement is used in conjunction with some user-defined exception type. Here is a simple example of the use of the THROW statement:

Exception    le_ex
le_ex = create Exception
Throw le_ex
MessageBox ("Hmm", "We would never get here if" &   
   + "the exception variable was not instantiated")

In this example, the code throws the instance of the exception le_ex. The variable following the THROW reserved word must point to a valid instance of the exception object that derives from Throwable. If you attempt to throw an uninstantiated Exception variable, a NullObjectError is thrown instead, indicating a null object reference in this routine. That could only complicate the error handling for your application.

Declaring exceptions thrown from functions

If you signal an exception with the THROW statement inside a method script—and do not surround the statement with a try-catch block that can deal with that type of exception—you must also declare the exception as an exception type (or as a descendant of an exception type) thrown by that method. However, you do not need to declare that a method can throw runtime errors, since PowerBuilder does that for you.

The prototype window in the Script view of most PowerBuilder painters allows you to declare what user-defined exceptions, if any, can be thrown by a function or a user-defined event. You can drag and drop exception types from the System Tree or a Library painter view to the Throws box in the prototype window, or you can type in a comma-separated list of the exception types that the method can throw.

Example

Example catching a user-defined exception This code displays a user-defined error when an arccosine argument, entered by the application user, is not in the required range. The try-catch block calls a method, wf_acos, that catches the system error and sets and throws the user-defined error:

TRY   
   wf_acos()
CATCH (uo_exception u_ex)   
   MessageBox("Out of Range", u_ex.GetMessage())
END TRY

This code in the wf_acos method catches the system error and sets and throws the user-defined error:

uo_exception lu_error
Double ld_num
ld_num = Double (sle_1.text)
TRY
   sle_2.text = string (acos (ld_num))
CATCH (runtimeerror er)   
   lu_error = Create uo_exception
   lu_error.SetMessage("Value must be between -1" &
      + "and 1")
   Throw lu_error
END TRY

Integration with EAServer

If you declare exceptions on a method of a user object and deploy the user object as a component to EAServer, the exceptions are translated to IDL (CORBA) as part of the method prototype. This means that PowerBuilder components in EAServer can be defined to throw exceptions that can be handled by any type of EAServer client application.

Other benefits for EAServer applications Another benefit for component development is that you can handle runtime errors in the component. If you do not handle an error, it is automatically translated into an exception and the component stops executing.

PowerBuilder client applications that use EAServer components can handle exceptions thrown by any type of EAServer component. If a Java EAServer component has a method on it that is defined to throw an exception and a PowerBuilder proxy is created to use that component, the method on the PowerBuilder proxy is also declared to throw a user-defined exception. The definition of the user-defined exception is created automatically at the time of the PowerBuilder proxy creation.

For more information about error handling in EAServer clients, see “Handling errors”.

IDL restrictions Deployment of components to EAServer imposes restrictions on the way you can use exception handling within PowerBuilder. Only the public instance variables defined on the exception type are actually translated to IDL. This is because IDL exceptions cannot have methods declared on them. Therefore if the exception type has methods defined on it, those methods can be called within the execution of the component but cannot be called by client applications that catch the exception thrown.

You must keep this restriction in mind when designing exception objects for distributed applications, exposing all exception information as public instance variables instead of through accessor methods on an exception object.

Two other interface restrictions also apply to exception types of a user object that is deployed as an EAServer component. Instance variables of exceptions on the user object methods cannot have object datatypes. Null data is supported only for instance variables with simple datatypes; if instance variables are structures or arrays, null values for individual elements are not maintained.