ActiveX client programming best practices
The best way to access Java components is to use the Java language. IBM recommends that you do as much programming as possible in the Java language and use a small simple interface between the COM Automation container (for example, Visual Basic) and the Java code. This interface avoids any overhead and performance problems that can occur when moving across the interface.
Best practice:
The following topics are covered:
- Visual Basic guidelines
- CScript and Windows Scripting Host
- Active Server Pages guidelines
- J2EE guidelines
Visual Basic guidelines
The following guidelines are intended to help optimize the use of the ActiveX to EJB bridge with Visual Basic:
- Launch the Visual Basic replication through the launchClientXJB.bat file. To run the Visual Basic application through the Visual Basic debugger, run the Visual Basic integrated development environment (IDE) within the ActiveX to EJB bridge environment. After you create the Visual Basic project, we can launch it from a command line; for example, launchClientXJB MyApplication.vbp. We can also launch the Visual Basic application alone in the ActiveX to EJB environment, by changing the Visual Basic shortcut on the Windows Start menu so that the launchClientXJB.bat file precedes the call to the VB6.EXE file.
- Exit the Visual Basic IDE before debugging programs.
Because the JVM code attaches to the running process, exit the Visual Basic editor before debugging the program. If we run the process, then exit your program within the Visual Basic IDE, the JVM code continues to run and you reattach the same JVM code when XJBInit() is called by the debugger. This causes problems if we try to update XJBInit() arguments (for example, classpath) because the changes are not be applied until you restart the Visual Basic program.
- Store the XJB.JClassFactory object globally.
Because we cannot unload or reinitialize the JVM code, cache the resulting XJB.JClassFactory object as a global variable. The overhead of treating this object as a global variable or passing a single reference around is much less than recreating a new XJB.JClassFactory object and calling the XJBInit() argument more than once.
CScript and Windows Scripting Host
The following guidelines intend to help optimize the use of the ActiveX to EJB bridge with CScript and Windows Scripting Host (WSH):
- Launch in ActiveX to EJB environment. Launch the VBScript files in the ActiveX to EJB bridge environment, to run VBScript files in .vbs files.
Two common ways exist to launch the script:
- launchClientXJB MyScript.vbs
- launchClientXJB cscript MyScript.vbs
Active Server Pages guidelines
The following guidelines intend to help optimize the use of the ActiveX to EJB bridge with Active Server Pages software:
- Use the ActiveX to EJB Helper functions from the Active Server Pages Application.
Because Active Server Pages (ASP) code typically use VBScript, we can use the included helper functions in any VBScript environment with minor changes.
See about these helper functions, see Helper functions for data type conversion. To run outside of the ASP environment, remove or change all references to the Server, Request, Response, Application and Session objects; for example, change Server.CreateObject to CreateObject.
- Set JRE path globally in system.
The XJB.JClassFactory object must be able to find the Java run time dynamic link library (DLL) when initializing.
In Internet Information Server, we cannot specify a path for its processes independently; set the process paths in the system PATH variable. We can only have a single JVM version available on a machine using the ASP application. Also, remember that after you change the system PATH variable reboot the Internet Information Server machine so that the Internet Information Server can see the change.
- Set the system TEMP environment variable.
If the system TEMP environment variable is not set, Internet Information Server stores all temporary files in the WINNT directory, which is usually not desired.
- Use high isolation or an isolated process.
When using the ActiveX to Java bridge with Active Server Pages software, creating the Web app in its own process is recommended. We can only load one JVM instruction in a single process and to have more than one application running with different JVM environment options (for example, different classpaths), then we need to have separate processes.
- Use the Application Unload option.
When debugging the application, use Unload when viewing the ASP application properties in the Internet Information Server administration console to unload the process from memory and thereby unload the JVM code.
- Run one process per application.
Use only one ASP application per J2EE application or JVM environment, in the ASP environment. If we need separate class paths or JVM settings, we need separate ASP applications (virtual directories with high isolation or an isolated process).
- Store the XJB.JClassFactory object in application scope.
Because of the one-to-one relationship required between a JVM instruction and a process, and because the JVM code can never detach or shut down from a process independently, cache the XJB.JClassFactory object at application scope and call the XJBInit() method only once.
Because the ActiveX to EJB bridge employs a free-threaded marshaler, take advantage of the multi-threaded nature of Internet Information Server and the ASP environment. If we choose to reinitialize the XJB.JClassFactory object at Page scope (local variables), then the XJBInit() method can only initialize the local XJB.JClassFactory variable. It is more efficient to use the XJBInit() method once.
- Use VBScript conversion functions.
Because VBScript code only supports variant data types, use the CStr(), CByte(), CBool(), CCur(), CInt(), Clng(), CSng() and CDbl() functions to tell the activeX to EJB bridge which data type we are using; for example oMyObject.Foo(CDbl(1.234)).
J2EE guidelines
The following guidelines are intended to help optimize the use of the ActiveX to EJB bridge with the J2EE environment;
- Store client container objects globally.
Because we can only have one JVM instruction per process, and a single J2EE client container (com.ibm.websphere.client.applicationclient.launchClient) per JVM instruction, initialize the J2EE client container only once and reuse it. For ASP applications, store the J2EE client container in an application level variable and initialize it only once (either on the Application_OnStart() event in the global.asa file or by checking to see if it IsEmpty()).
A side effect to storing the client container object globally is that we cannot change the client container parameters without destroying the object and creating a new one. These parameters include the EAR file, BootstrapHost, class path, and so on. If we run a Visual Basic application and want to change the client container parameters, end the application and restart it. If we run an Active Server Pages application, first unload the application from Internet Information Server (see "Use the Application Unload Button" under Active Server Pages guidelines). Then load the Active Server Pages application with the different client container parameters. The parameters set the first time the Active Server Pages application loads. Since the client container is stored on the Internet Information Server, all the browser clients share the parameters using the Active Server Pages application. This behavior is normal for Active Server Pages code, but can be confusing when you try to run to different WASs using the same Active Server Pages application, which is not supported.
- Reuse custom temporary directory for EAR file extraction.
By default, the client container launches and extracts the application .ear file to the temp directory and then sets up the thread class loader to use the extracted EAR file directory and the JAR files included in the client JAR manifest. This process is time consuming and because of some limitations with JVM shutdown through Java Native Interface (JNI) and file locking, these files are never cleaned up.
Specifically, each time the client container launch() method is called, it extracts the EAR file to a random directory name in the temporary directory on the hard drive. The current Java thread class loader is then changed to point to this extracted directory which in turn locks the files within. In a normal J2EE Java client, these files automatically clean up after the application exits. This cleanup occurs when the client container shutdown hook is called (which never happens in the ActiveX to EJB bridge), which leaves the temporary directory there.
To avoid these problems, we can specify a directory to extract the EAR file by setting the com.ibm.websphere.client.applicationclient.archivedir Java system property before calling the client container launch() method. If the directory does not exist or is empty, you extract the EAR file normally. If the EAR file was previously extracted, the directory is reused. This feature is particularly important for server processes (for example, ASP), which can stop and restart, potentially calling the launchClient() method several times.
If we need to update the EAR file, delete the temporary directory first. The next time you create the client container object, it extracts the new EAR file to the temporary directory. If we do not delete the temporary directory or change the system property value to point to a different temporary directory, the client container reuses the currently extracted EAR file, and does not use the changed EAR file.
When specifying the com.ibm.websphere.client.applicationclient.archivedir property, verify the directory you specify is unique for each EAR file you use. For example, do not point MyEar1.ear and MyEar2.ear files to the same directory.
If we choose not to use this system property, go regularly to the Windows temp directory and delete the WSTMP* subdirectories. Over a relatively short period of time, these subdirectories can waste a significant amount of space on the hard drive.
Related tasks
Develop ActiveX client application code