Chapter 20 Creating ActiveX Clients
To write and test code for your ActiveX client, you must be connected to a Jaguar server (or have the Jaguar 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 the Jaguar server on your machine, you have the option to install the ActiveX runtime files as well. For more information, see the Enterprise Application Server Installation Guide for Windows or the Enterprise Application Studio Installation Guide for Windows.
Before invoking methods on component instances, the client must connect to a Jaguar 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 Jaguar 1.1 style clients:
The ORB, SessionManager, and other CORBA-style interfaces are documented in Chapter 4, "ActiveX Client Interfaces" in the Jaguar CTS API Reference.
Proxies are local objects that allow you to call Jaguar component methods as if the component were a local object in your program. Instantiate proxies using the Jaguar ORB and SessionManager::Manager interfaces, as follows:
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 17, "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 Jaguar 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 Jaguar server. To create a Manager instance, you must identify a server listener using a URL of the format:
protocol://host:port
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 Jaguar 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
Jaguar 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 Bean 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 Jaguar 1.1 interface is provided for backward compatibility with existing applications.
To invoke Jaguar components, your ActiveX client should:
Proxy objects are instantiated and invoked via ActiveX dispatch interfaces. Jaguar 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 Baror
Set bar = New Bar
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 Jaguar 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 Jaguar 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 Jaguar CTS 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 Jaguar server's Initial
Context
property. The syntax for the Name
property
is:
"package/component"
If the Name
property
is not specified, or defined incorrectly, the default is used.
To instantiate the components on the Jaguar server, use the Initialize() method. Initialize() establishes
a connection to the Jaguar server, using the connection properties
you set in the previous step. If the Jaguar 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 Jaguar server an instance of the Employee component belonging
to the Company package.
employeeproxy.Initialize()
"ActiveX datatype support" lists the ActiveX types supported by Jaguar, as well as the equivalent Jaguar Manager and CORBA IDL types.
Jaguar 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 a Jaguar 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:
The following table lists the codes for server-side error numbers defined in the JagORBServerErrNum enumeration:
By default, the ActiveX proxy raises an ActiveX exception when a Jaguar 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:
This example calls a method CtsSecurity.SSLServiceProvider.setGlobalProperty. This method can be called to specify SSL settings for a connection to a Jaguar server (see Chapter 21, "Using SSL in ActiveX Clients" 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 © 2000 Sybase, Inc. All rights reserved. |