Handling exceptions inline

By default, the ActiveX proxy raises an ActiveX exception when an EAServer component method raises an exception or an internal error occurs. Visual Basic and most other ActiveX scripting tools do not allow you to handle these errors inline. Instead, control transfers to an error handler (specified by on error goto in Visual Basic) or to a system-wide error dialog box.

Inline exception handling can simplify the code that handles recoverable errors. For example, you can keep program logic that allows a user to retry a failed login in one place, rather than split into mainline code and the separate error handling code. Inline exception handling also allows you to handle errors explicitly in scripting tools that do not allow you to install user-coded error handlers.

The ActiveX proxy supports inline exception handling with Try, Catch, and End methods and an internal exception store. When an exception occurs with inline handling active, the proxy stores the error information rather than raising an ActiveX exception. Each component proxy object supports these methods and contains an exception store that is specific to that object. To handle exceptions inline, call the Try_, Catch_, and End_ methods as follows:

Special considerations

The Try_ and Catch_ methods do not have the same semantics of structured exception handling in Java or C++. In particular:

Example: using "catch all" exception handling

When you call the Catch_ method, you can check for exceptions of a specific type, or for exceptions of any type. To check for any exception, pass “...” as the exception type parameter.

The following example illustrates this style of exception handling:

barcomp.Try_
barcomp.methodThatRaisesException(1007)
Dim anyExcep As Object
If (barcomp.Catch_("...", anyExcep) = True) Then
    Dim excepType as String
    excepType = anyExcep.GetExceptionType
    if (StrComp(excepType, "Foo/NotValidIdException") == 0) then
       Dim invalidIdExcep as NotValidIdException
       set invalidIdExcep = anyExcep
       Dim id as integer
       Dim msg as String
       id = invalidIdExcep.id
       msg = invalidIdExcep.message
    Else if (StrComp(excepType, "Foo/NoAuthorizationException") == 0) then
        Dim noAuthorizationExcep as NoAuthorizationException
        set noAuthorizationExcep = anyExcep
        Dim user as String
        Dim cert as String
        user = noAuthorizationExcep.username
        cert = noAuthorizationExcep.certificate
    Else if (StrComp(excepType, "Jaguar/ClientException") == 0) then
        Dim systemExcep as SystemException
        set systemExcep = excep
        Dim code as integer
        Dim msg as String
        code = systemExcep.code
        msg = systemExcep.message
    End if
    Else
        ' No Exception has occurred. Proceed
End If

Exception datatypes

Exception datatypes are used with the Try_ method when handling exceptions inline. The ActiveX proxy includes predefined system exceptions that correspond to the standard CORBA system exceptions. User-defined exceptions that are declared in an IDL module are also mapped to ActiveX types.

System exceptions In IDL, system exceptions extend the CORBA SystemException IDL type:

interface SystemException
{
  long code;      // numeric error code
  string message; // text error message
};

Unlike user-defined exceptions, a component method can throw system exceptions that are not listed in the raises clause of the IDL method signature. The C++ and ActiveX client runtime engines may also raise system exceptions when errors occur in the processing of a method invocation.

In the ActiveX proxy, system exceptions are mapped to the interface SystemException with the following properties and methods:

The ActiveX proxy uses SystemException to represent the standard CORBA system exception types that can be returned by components, as well as errors that occur in the ActiveX proxy. “Exception identifiers” lists the system exception types.

User-defined exceptions In IDL, user-defined exceptions are defined using syntax similar to an IDL structure. For example:

exception InvalidValueException
{
  string message;
  string value;
};

User-defined exceptions can be defined within an IDL module or interface. The IDL method signature for a component method must list user-defined exceptions thrown by the method in the raises clause. A method cannot throw user-defined exceptions that are not listed in the raises clause.

In ActiveX, the IDL exception maps to an interface with the following properties and methods:

Exception identifiers Both system and user-defined exceptions support a GetExceptionType method that returns a string identifier for the exception. The exception identifier for a user-defined exception defined in a module is:

module/exception 

Where module is the IDL module name and exception is the IDL exception type. For example, “CtsSecurity/No Certificate Exception”. The exception identifier for an exception defined in an interface is:

module/interface/exception 

Where interface is the IDL interface name.

Exception identifiers for system exceptions are predefined, as listed in Table 20-3.

Table 20-3: System exception identifiers

Identifier

Notes

Jaguar/ClientException

An error occurred internally to the ActiveX proxy. For example, you may have called a method that uses an unsupported parameter type.

CORBA/BAD_CONTEXT

CORBA/BAD_INV_ORDER

CORBA/BAD_PARAM

CORBA/BAD_OPERATION

CORBA/BAD_TYPECODE

CORBA/COMM_FAILURE

A network error occurred. When creating a connection, this usually indicates that the server is down or you have specified the wrong listener address. When calling a method, the error may indicate a transient network fault; you can retry the method.

CORBA/DATA_CONVERSION

CORBA/FREE_MEM

CORBA/IMP_LIMIT

CORBA/INTERNAL

CORBA/INTF_REPOS

CORBA/INV_FLAG

CORBA/INV_IDENT

CORBA/INV_OBJREF

CORBA/INVALID_TRANSACTION

CORBA/INITIALIZE

CORBA/MARSHAL

CORBA/NO_IMPLEMENT

The component does not implement the method that you called.

CORBA/NO_MEMORY

CORBA/NO_RESOURCES

CORBA/NO_RESPONSE

CORBA/NO_PERMISSION

The user cannot access the server or a specified component.

CORBA/OBJ_ADAPTER

CORBA/OBJECT_NOT_EXIST

The object does not exist. This can happen if:

  • The component is not installed correctly on the server. For example, the component class or skeleton class cannot be loaded.

  • The object represents a stateful component and your reference to it has expired. Check the value of the component’s Instance Timeout property, and, if needed, code your client to create another instance in response to this error.

CORBA/PERSIST_STORE

CORBA/TRANSACTION_REQUIRED

The method you attempted to call must be called in the context of an open transaction.

CORBA/TRANSACTION_ROLLEDBACK

The method you called rolled back its transaction, or if you have started a client-managed transaction, the transaction timed out.

CORBA/TRANSIENT

CORBA/UNKNOWN

Example

This example calls a method CtsSecurity.SSLServiceProvider.setGlobalProperty. This method can be called to specify SSL settings for a connection to a server. For more information, see Chapter 8, “Using SSL in ActiveX Clients,” in the EAServer Security Administration and Programming Guide.

The method signature and the exceptions raised are detailed in the following IDL:

module CtsSecurity
{
  interface SSLServiceProvider
  {
    string setGlobalProperty
    (
      in string property,
      in string value
    )
    raises (CtsSecurity::InvalidPropertyException,
      CtsSecurity::InvalidValueException);
  };
  
  exception InvalidPropertyException
  {
    string message;
    string property;
  };
  
  exception InvalidValueException
  {
    string message;
    string value;
  };
};

setGlobalProperty raises InvalidValueException if you attempt to set a property to an invalid value, and raises InvalidPropertyException if you specify a property that does not exist.

The following Visual Basic code calls setGlobalProperty and calls the Catch method to handle InvalidValueException inline. Since there is no Catch_ call for InvalidPropertyException, if this exception is thrown, it will be thrown as an ActiveX exception when End_ is called:

Dim ssp as CtsSecurity.SSLServiceProvider

// Assume ssp has been properly initialized

Dim ivException as CtsSecurity.InvalidValueException
// Activate inline exception handling
call ssp.Try
ssp.setGlobalProperty("qop", "An invalid value")
if (ssp.Catch_("CtsSecurity/InvalidValueException", ivException) then
  call MessageBox ("Invalid value: " & ivException.value & ". " & _
              ivException.message, , "Error");
endif
call ssp.End_

Using Try_ and Catch_ in multithreaded programs

If your program uses a proxy object in multiple threads and handles exceptions inline, you must call the Duplicate_ method to obtain a copy of the proxy object for use in each thread. Duplicate_ has the following syntax:

Object Duplicate_

Duplicate_ returns a proxy instance of the same type as the original.