Chapter 19: Creating ActiveX Components
Defining an ActiveX component means defining the interfaces, transaction properties, and instance properties. If you define an ActiveX component in EAServer before implementing the ActiveX component, the client developer can build the client at the same time you are building the ActiveX component. You can write the entire component in your IDE first and then import it into EAServer, where you set the properties, but in this case, the client cannot be developed concurrently with the component.
You can also individually define each method and parameter using EAServer Manager. After defining the interfaces, you can use EAServer Manager to define the transaction and instance properties.
Chapter 4, “Defining Components” describes how to define and configure new components in EAServer Manager. Chapter 5, “Defining Component Interfaces” describes how to define methods in the component interface.
WARNING! When you define an ActiveX component, you must enter the ProgID. Do not use underscores in the ProgID for the component—use a period instead.
EAServer Manager can import ActiveX components from the component’s type library (.tlb file) file or DLL. When you import the ActiveX component, it is automatically added to the EAServer IDL repository. All CoClass classes (component object model classes) in the ActiveX component are imported.
Imported interfaces must conform to all EAServer requirements for ActiveX components. (The requirements are listed in “Defining methods”.)
Importing components does not import TabularResults::ResultSet and TabularResults::ResultSets return types. If a method in the imported component returns a result set, then you must use EAServer Manager to change the return value to TabularResults::ResultSet or TabularResults::ResultSets in EAServer Manager.
Before you can use the ActiveX import feature, make sure that you register the .dll file using the Windows utility, regsvr32.exe:
regsvr32 <fully qualified path name to dll>
If you change the location of the .dll file after registration, you must reregister the file with the new location.
To import an ActiveX file:
Double-click the Packages folder to expand it.
Highlight the package to which the component will be added.
If installing to the Components folder, highlight the Components folder.
Select File | Install Component from the menu.
In the Component wizard dialog, select Import from ActiveX File, then click OK.
If the Import from ActiveX File option is not displayed, you are running EAServer Manager or the server on UNIX. You cannot create ActiveX components when either EAServer Manager or the server is running on UNIX.
Enter the fully qualified path name of the .tlb or .dll file from which you are importing. Some development environments do not automatically generate .tlb files. Enter the name of the .dll file if this is the case. You can use the browse feature to locate either file.
Click OK. The component is imported; the component name is the ProgID without the version number and with periods replaced by underscores. You can view the new component along with its methods and parameters from the EAServer Manager.
To define methods, you must specify each method’s return type and the number, datatypes, and modes of the method’s parameters. See “ActiveX datatype support” for more information.
Do not use two consecutive underscores in method names—the underscores and the text following the underscores are deleted when stubs and skeletons are generated. This issue is related to function overloading, which is allowed in Java and C++ but not in ActiveX components. See “Operation declarations” for more information.
WARNING! You cannot define methods with names that differ only in case—IDL does not support this.
ActiveX component methods can return any valid datatype. Methods can take zero or more parameters. For each parameter you add, you must specify a name, a datatype, and the argument mode. Datatypes are limited to those supported by EAServer Manager. “ActiveX datatype support” describes the supported types.
The transaction property specifies how a component participates in transactions. You can view and change the transaction property using the Transactions tab of the component’s property sheet. For a description of each option on the Transactions tab, see “Transactional component attribute”. A transaction consists of a number of database updates (which can be performed by multiple components) that are grouped into a single atomic unit of work.
This information is not stored in the EAServer repository, so if you import a component, you must configure this property manually after importing it.
For a full description of how EAServer handles transactions, Chapter 2, “Understanding Transactions and Component Lifecycles”
Instance properties impose constraints on concurrent execution of the different component instances. You can view and change instance properties using the Instances tab of the component’s property sheet.
If you import a component interface, you must configure this property manually after importing the component. This information is not stored in the EAServer repository.
EAServer supports only the ActiveX single-threaded apartment model. In the single-threaded apartment model, each component instance is bound to the same thread for the lifetime of the instance. A thread is serviced by the same connection. Multiple instances may be simultaneously active on different threads. Shared stateful resources and global data should not be used.
To implement the single-threaded apartment model for an ActiveX component, enable only the Bind Thread option in the component properties Instances tab. Although most ActiveX-enabled IDEs use the single-threaded apartment model, if a component uses the ActiveX free-threaded model (in which a single method invocation can run on different threads), the component defaults to using the ActiveX single-threaded apartment model. ActiveX components developed with Power++ support the single-threaded apartment model.
Because Visual C++ 4.2 ActiveX components use nonapartment single-threading (in which multiple instances cannot be simultaneously active) by default, you must change them to use the single-threaded apartment model by:
Not using global data, and
Marking the component’s Registry entry to indicate that the component supports the single-threaded apartment model.
The following settings specify the constraints that are placed on concurrent execution of different instances of the component. The choices are:
Concurrency – Multiple invocations can be processed concurrently; that is, multiple instances can be simultaneously active on different threads. The component must be thread-safe. Use this setting if the component code uses no volatile global data and does not share stateful resources (such as a file) among instances. This threading model offers the highest performance.
Bind Thread – Instances are bound to the creating thread. The component uses thread-local storage.
Pooling – Instances are pooled after a commit or rollback. Instance pooling allows EAServer to recycle component instances, avoiding the overhead incurred when a new instance is created each time a component is activated.
When deciding whether to support instance pooling, consider the following factors:
Instance pooling increases the efficiency of your component the most when more resources are used to initialize an instance than to clean it up. Complex structures that incur a large overhead to create are prime candidates for instance pooling. If the component does not perform a lot of initialization, it may not be more efficient for a component to use instance pooling.
Transactional components can benefit from instance pooling. Each time an EAServer transaction is committed or rolled back, EAServer deactivates the component instances that are involved. If your component does not support instance pooling, a new instance is required for each EAServer transaction that the component participates in.
You might also want to implement the IObjectControl interface in place of or in conjunction with the pooling option. Implement the IObjectControl interface if you:
Want to determine, at runtime, whether a specific instance should be pooled (do not select the pooling option—otherwise, the CanBePooled method in the IObjectControl interface will not be called), or
Need to reset the component’s state after deactivation.
Only if you are coding the component in C++ can you directly implement IObjectControl.
Sharing – A single shared instance services all client requests. Only one instance of the component can exist at any time. Attempts to create new instances when one already exists will fail.
|Copyright © 2005. Sybase Inc. All rights reserved.|