Chapter 18 Creating ActiveX Clients
To write and test code for your ActiveX client, you must be connected to a server (or have the server running on your machine) and have the ActiveX runtime files installed on your machine. To install the ActiveX runtime files, see "Deploy the ActiveX client"; if you install EAServer on your machine, you have the option to install the ActiveX runtime files as well. For more information, see the EAServer Installation Guide.
Before invoking methods on component instances, the client must connect to a server and instantiate the components. There are two techniques for proxy instantiation:
If you currently have ActiveX proxy automation server clients, Sybase recommends that you migrate you current ActiveX clients to use the CORBA-style so that you can take advantage of the new benefits. The following features are available to CORBA style clients and not to EAServer 1.1 style clients:
The ORB, SessionManager, and other CORBA-style interfaces are documented in Chapter 4, "ActiveX Client Interfaces" in the EAServer API Reference.
Proxies are local objects that allow you to call EAServer component methods as if the component were a local object in your program. Instantiate proxies using the EAServer ORB and SessionManager::Manager interfaces, as follows:
Step | What it does | Detailed explanation |
---|---|---|
1 | Initialize the CORBA ORB and create an ORB reference. | "Initializing the ORB" |
2 | Use the ORB reference to create a Manager instance for the server. | "Creating a Manager instance" |
3 | Use the Manager instance to create a Session. | "Creating sessions" |
4 | Use the Session instance to create stub component instances. | "Creating stub instances" |
5 | Call the stub methods to remotely invoke component methods. | "Invoke component methods" |
If you are using Visual Basic, before using the ORB,
Session, Factory, and Manager objects in your client, create references
to JaguarORB.tlb, SessionManager.tlb and CtsSecurity.tlb in
your Visual Basic project using the standard Visual Basic mechanism.
Before any ORB classes can be used, you must call the init method, which:
The ORB.init() method acceps a formatted
string that can contain settings for multiple initialization parameters.
Pass initialization parameters as shown in this example, which configures
the -ORBlogFile
property and
the -ORBpin
property, to specify
a file name for logging errors and the Sybase SSL-certificate-database
password, respectively:
orb.init("-ORBlogFile=d:\jagorb.log,-ORBpin=sybase")As shown in the example, parameter names and values must be separated by an equals sign, '=', and each name/value pair must be separated from the next with a comma and no white space.
For each initialization parameter, there is an equivalent environment variable. If the environment variable and initialization parameter are set, the value of the initialization parameter is used. Parameter and environment variable names are the same as for the C++ client ORB (see Chapter 15, "Creating CORBA C++ Clients").
You can set any initialization parameter to a value of none, which overrides the value of the environment variable and sets the value to the default, if any.
You can pass the following initialization parameters to the driver class:
iiop://hostname:iiop-port/initial-context
USA/Sybase/
,
all names that you resolve with the context are assumed to be relative
to this location in the name hierarchy. When specifying the initial
context, a trailing slash is optional; it is added automatically
if you do not specify an initial context that ends with a slash.
iiop://host1:9000;iiop://host2:9000/USA/Sybase/
ORB initialization is demonstrated in the following example.
Dim orb As ORB Dim Manager As Manager Dim Session As Session Dim Factory As Factory ' Create a new ORB object Set orb = New ORB ' Initialize the ORB instance orb.init ("")
init returns an object reference to the EAServer ORB. When orb is deallocated or assigned a new object reference, it will be automatically released.
The SessionManager::Manager interface is used for interacting with a server. To create a Manager instance, you must identify a server listener using a URL of the format:
protocol://host:port
where:
iiop
or iiops
.
Use iiops
for connections to
secure iiop
listeners.
Pass the URL to the string_to_object method to convert the URL string into a Manager instance, as shown in the following example. The object returned by string_to_object must be narrowed to the SessionManager/Manager interface.
Dim orb As ORB Dim Manager As Manager Dim obj as Object ... deleted orb initialization ... Set obj = orb.string_to_object( "iiop://puddle:9000") Set Manager = obj.Narrow_("SessionManager/Manager") ...
The SessionManager::Session interface represents an authenticated session between the client application and a server. The createSession method accepts a user name and password and returns a session object, as shown in the example below:
Dim orb As ORB Dim Manager As Manager Dim Session as Session Dim obj as Object ...deleted manager initialization Set obj = Manager.createSession("jagadmin","") Set Session = obj.Narrow_("SessionManager/Session") ...
You call the Session.lookup method to return an object reference factory. You then use the factory to create one or more proxies for the component.
lookup takes a string that specifies the
EAServer component name. By default, the name is package/component,
where package is the Jaguar Manager package
name and component is the component name. Package
and component names are not case sensitive. Component developers
can override the default name by setting the JNDI Name property
for EJB components, or the com.sybase.jaguar.component.bind.naming
property
for other types of components.
lookup returns a CORBA::Object reference. You use Narrow_ to convert the object reference into an instance of the factory for the component.
After instantiating the factory, the factory Create method returns an instance of the component proxy.
The code to instantiate a proxy for a component named Foo/Bar looks like this:
Dim Session as Session Dim fact as Factory Dim barComp as Bar // Component proxy Dim obj as Object ...deleted session initialization ... Set obj = Session.lookup("Foo/Bar") Set fact = obj.Narrow_("SessionManager/Factory") Set barComp = fact.Create()
Sybase recommends that you use the CORBA style interfaces for new development. The EAServer 1.1 interface is provided for backward compatibility with existing applications.
To invoke EAServer components, your ActiveX client should:
Proxy objects are instantiated and invoked via ActiveX dispatch interfaces. EAServer proxy objects can be identified by their program identifier (ProgID). See "Check the ProgID for each interface" for more information.
Different ActiveX-enabled IDEs have different mechanisms for declaring an ActiveX object. In Visual Basic, you can simply declare the proxy object and instantiate it. For example, you can write either one of the following to instantiate a proxy object:
Dim bar as Bar Set bar = New Baror
Dim bar as Object Set bar = CreateObject("Foo.Bar")
Although the ActiveX proxy object exists once you have declared it, you cannot invoke methods until after you have set connection properties and called the Initialize method.
Before
calling the Initialize method, set the connection
properties, such as UserName
, Password
, Host
,
and Name
. The ActiveX client
uses connection properties to connect to the server. This example
sets the connection information for the employeeproxy
object.
employeeproxy.UserName = "Guest" employeeproxy.Password = "Guest" employeeproxy.Host = "Jaguar" employeeproxy.Name = "Company/Employee"
The user name and password, which must be specified, are required for login authentication and access control. The defaults for user name and password are empty strings. If the server administrator has enabled authentication, you must use a valid user name and password. If user access to the package or component is limited, the user name must be in a group that has access to the component. For more information on security, see "Security Configuration" in EAServer Administration Guide.
The Host
property,
which is optional, is the machine name and IIOP port number or the
environment variable that specifies the machine name and IIOP port
number. If the machine name and IIOP port number are specified for
the Host
property, the
environment variable is ignored. See "Deploy the ActiveX client" for more information about defining
the environment variable.
The syntax for specifying the machine name and IIOP port number is:
"machine:port"
where:
machine is the machine name.
port is the IIOP port number.
If the
Host
property
or environment variable is not specified, or defined incorrectly,
the default, which is "localhost:9000", is used.
The Name
property,
which is optional, specifies the package and component names. By
default, the package name is the same as the module name, and the component
name is the same as the interface name. Specify the Name
property when
a component's package or component name is different from
its module or interface name. The package and component are automatically
located relative to the server's Initial
Context
property. The syntax for the Name
property
is:
"package/component"
where:
If the
Name
property
is not specified, or defined incorrectly, the default is used.
To instantiate the components on the server, use the Initialize() method. Initialize() establishes
a connection to the server, using the connection properties you
set in the previous step. If the server host name is not valid,
or if another error occurs, the APAS displays an error message.
This example executes the Initialize() method
on the employeeproxy
object,
and instantiates on the server an instance of the Employee component
belonging to the Company package.
employeeproxy.Initialize()
"ActiveX datatype support" lists the ActiveX types supported by EAServer, as well as the equivalent Jaguar Manager and CORBA IDL types.
EAServer components appear as automation objects in the ActiveX-enabled IDE. If your IDE supports it, you can simply drag and drop the component method into your ActiveX client code and use the IDE's object browser to see the component's method syntax. You must call the proxy methods using the syntax required by your development tool.
To execute a component method, execute the method on the proxy
object. In this example, the GetEmployeeInfo() and
the SetEmployeeInfo() methods are executed on employeeproxy
.
The parameters in the SetEmployeeInfo() method
are in parameters. The parameters in the GetEmployeeInfo() method
are inout parameters.
String name Long age String sex name = "John" age = 32 sex = "male" // Example for parameters using the in argument mode employeeproxy.SetEmployeeInfo (name, age, sex) // Example for parameters using the inout argument mode employeeproxy.GetEmployeeInfo (REF name, REF age, REF sex)
Methods may return result sets. After a method invocation, you can retrieve result sets as described in "Result-set support".
If a component that the ActiveX client accesses is an
ActiveX component and a C++ IDE such as Visual
C++ was used to develop it, string parameter types
are always passed by reference (as BSTR *). Make sure that
you defined these parameters as inout in Jaguar
Manager.
When you invoke component methods, these restrictions apply:
Always make sure that your application handles exceptions gracefully. At minimum, you should display the exception text, which will aid debugging.
Errors in ActiveX proxy execution can be handled as ActiveX exceptions, or inline using a try/catch model similar to the structured exception handling model in the C++ and Java languages.
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. To handle proxy errors inline, you must enable inline exception handling as described in "Handling exceptions inline".
In C++, the OLE EXCEPINFO structure describes an ActiveX exception. Different ActiveX-enabled IDEs provide different mechanisms for applications to obtain the EXCEPINFO structure contents.
In Visual Basic, exceptions are mapped to the built-in Err object. The exception number maps to Err.Number and the description is available as Err.Description. You can handle exceptions by activating error handling code with On Error Goto statement or by checking whether Err.Number is > 0.
The proxy type library defines error numbers for client-side errors in the JagORBClientErrNum enumeration and server-side error numbers in the JagORBServerErrNum enumeration.
IDL user-defined exceptions are not supported and are
mapped to error number 9000.
The following table lists the codes for client-side error numbers defined in the JagORBClientErrNum enumeration:
Symbolic error code | Number | Description |
---|---|---|
jagClNonByteArrayErr | 8000 | Method arguments of type array can only have a base element type of byte. |
jagClMultiDimArrayErr | 8001 | Multi-dimensional arrays not supported as an argument to a method. |
jagClArrayRedimErr | 8002 | A Fatal Internal Error was encountered while attempting to resize a method argument of type array. |
jagClArrayProcErr | 8003 | A Fatal Internal Error was encountered while processing a method argument of type array. |
jagClArrayEmptyErr | 8004 | An array of size 0 was passed as parameter to a method. |
jagClArrayBoundsErr | 8005 | A Fatal Internal Error was encounterd while attempting to determine the upper bound on a method argument of type array. |
jagClNotJagComponentErr | 8006 | The component being instantiated is not a valid EAServer component or was not registered in the Windows Registry. |
jagClOutOfMem | 8007 | The Application failed to acquire memory from the Operating System. |
jagClCreateFactErr | 8008 | The EAServer Proxy Server could not instantiate a Factory Object. Please contact Sybase Technical Support. |
jagClTypeLibErr | 8009 | The type library for the Component could not read from the Windows Registry. Please check if a valid directory location was specified for the Type Library while registering the component. |
jagClTypeInfoErr | 8010 | The type information for the Component could not read from the Type Library. Please regenerate TLB and REG files for the component using Jaguar Manager. |
jagClMethInfoErr | 8011 | The metadata for the method or component could not be read from the Windows Registry or the method is using parameter types that are not presently supported in the EAServer ActiveX Proxy. |
jagClMethNameErr | 8012 | The metadata for the method invoked on component could not be read from the Windows Registry. Please regenerate TLB and REG files for the component using Jaguar Manager. |
jagClCompNameErr | 8013 | The component name for the component being instantiated could not read from the Windows Registry. |
jagClPkgNameErr | 8014 | The package name for the Component being instantiated could not read from the Windows Registry. |
jagClPxyCreateErr | 8015 | Component creation failed. |
jagClPxyDestroyErr | 8016 | Component deletion failed. |
jagClPxyFuncDescErr | 8017 | The metadata information for the method could not read from the type library. |
jagClArgCountErr | 8018 | There was a mismatch between the number of parameters passed to method and the number of parameters as described by the information in the type library. |
jagClInternalErr | 8019 | An error was encountered while invoking an EAServer method. |
jagClParamInfoErr | 8020 | The type information for a method parameter could not be read from the Type Library. |
jagClTypeMismatchErr | 8021 | There is a mismatch between type of the value passed as an argument with its specified type in the Type Library. |
jagClConversionErr | 8022 | The data conversion attempted is presently not supported. |
jagClArgUpdateErr | 8023 | An error was encountered while updating an input-output or output parameter for a method. |
jagClRetValSetErr | 8024 | An error was encountered while updating the return value for a method. |
jagClRecsetArgErr | 8025 | The ResultSet type cannot be passed as a parameter in either the input or input-output modes by an EAServer ActiveX application. |
jagClUnsuppTypeErr | 8026 | An unsupported OLE Automation type was used as a parameter in a method. |
jagClAxConvertErr | 8027 | An error was encountered while converting a input-output method parameter received from the server. |
jagClJagConvertErr | 8028 | An error was encountered while converting a input parameter prior to method invocation. |
jagClNoInitErr | 8029 | an EAServer component instance must be created prior to invoking a method. |
jagClRecordsetCreateErr | 8030 | An internal error was encountered while creating the Recordset object. |
jagClRecordsetMoveErr | 8031 | Attempt to call MoveNext on a RecordSet which has its EOF property as TRUE. |
jagClIteratorPosErr | 8032 | An invalid position was specified while attempting to retrieve an element from a collection. |
jagClInvalidMethodErr | 8033 | The only method supported on the generic Object type is Narrow_. |
jagClNarrowFailErr | 8034 | The object reference cannot be narrowed to the interface name specified. |
jagClInvalidIntfErr | 8035 | The fully scoped interface name passed as an argument to the Narrow_ method is invalid. |
jagClOrbInitErr | 8036 | An internal error was encountered while initializing client-side ORB. |
jagClOrbStrToObjErr | 8037 | An internal error was encountered while invoking the ORB.string_to_object method. |
The following table lists the codes for server-side error numbers defined in the JagORBServerErrNum enumeration:
Symbolic error code | Number | Description |
---|---|---|
jagSrvMethExcepErr | 9000 | The method implementation threw an user-defined exception while executing on the server. |
jagSrvMethInvalidErr | 9001 | The method name is either invalid or is presently not defined in the component's interface. |
jagSrvMethInvalidArgErr | 9002 | The invocation of the method on the server failed because an invalid number of parameters was passed or a parameter type mismatch occurred. |
jagSrvMethNotImplErr | 9003 | The invocation of the method on the server failed because the component does not implement the method. |
jagSrvCompPermErr | 9004 | The invocation of the method on the server failed because user does not have the permissions to instantiate the component. |
jagSrvCompDeployErr | 9005 | The invocation of the method on the server failed because component implementation was not deployed on the server. |
jagSrvInternalErr | 9006 | The invocation of the method on the server failed due a fatal internal error. |
jagSrvArgCountErr | 9007 | The invocation of the method on the server failed because an invalid parameter type was used by the method. |
jagSrvSrvConnectErr | 9008 | The requested operation failed since the client could not to acquire connection to the server. |
jagSrvConversionErr | 9009 | The invocation of the method on the server failed due to a data conversion error. |
jagSrvFreeMemErr | 9010 | The invocation of the method on the server failed while releasing memory resources. |
jagSrvIntfReposErr | 9011 | The invocation of the method on the server failed while trying to access the interface repository. |
jagSrvOutOfMemErr | 9012 | The invocation of the method on the server failed while trying to acquire memory from the Operating System. |
jagSrvOutOfResErr | 9013 | The invocation of the method on the server failed since it could not acquire the necessary resources. |
jagSrvSrvRespErr | 9014 | The invocation of the method on the server failed because there was no valid response from the server. |
jagSrvInvObjrefErr | 9015 | The invocation of the method on the server failed because the object reference is invalid. |
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:
boolean Catch_( in string exceptionType, out Object exception )
The Try_ and Catch_ methods do not have the same semantics of structured exception handling in Java or C++. In particular:
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 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 and listed in the following table:
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:
|
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 |
This example calls a method CtsSecurity.SSLServiceProvider.setGlobalProperty. This method can be called to specify SSL settings for a connection to a server (see the EAServer Security Administration and Programming guide for more information).
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_
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.
Copyright © 2002 Sybase, Inc. All rights reserved. |
![]() |