Session-specific Classpath

Introduction

Prior to BBj 9.0, all BBj sessions shared the classpath of BBjServices and there was no way to make classes that were not in the classpath of BBjServices become visible to a BBj session without restarting BBjServices. BBj 9.0 introduced the concept of a session-specific classpath (SSCP) to allow a BBj session to use Java classes that are not found in the BBjServices classpath.

Use Cases for SSCP

The motivation for SSCP came from the following use cases:

  • When developing user-defined java classes, it should be possible to modify those classes and test the modifications without restarting BBjServices

  • It should be possible for two BBjSessions to run with different versions of user-defined Java classes

  • For the libraries provided by the ExtIndex.jar, it is possible for a particular BBjSession to use a different version of that library than the version that is provided by the BBj install.

Overview

An SSCP is an alternate classpath that a BBj session can use. A unique name identifies that SSCP and can be defined either in the Enterprise Manager or by invoking methods on BBjAPI. Then simply specify that name when starting a new BBj session, either from the command line or using BBjCommandLineObject.setClasspathName().

Creating or Modifying an SSCP...

...Using Enterprise Manager in Eclipse

To create and/or modify an SSCP, go to the 'Classpath Names' section in BBj Services - Java Settings.

To enable/disable 'Recheck Session Classpath', go to the Thin Client Performance section in BBjServices - Settings.

...Using Enterprise Manager in Java GUI (deprecated)

Create and/or modify an SSCP from the Classpath tab of the Server Information section of Enterprise Manager. To create a new classpath, click the "plus" next to the "Classpath Names" list. Type a new name in dialog and press [OK]. To modify a classpath, add, remove or change the order of the Classpath entries in the "Classpath Entries" list using the buttons on the right. Click the [Save] button at the bottom of the Enterprise Manager window to save the new or modified SSCP. For more information, see the  Enterprise Manager - Server Information.

...Using BBjAPI

Create an SSCP within the BBjAPI using code similar to the following:

admin! = BBjAPI().getAdmin(adminName$, adminPassword$)
env! = admin!.getEnvironment()
vec! = BBjAPI().makeVector()
vec!.add("/dev/testSSCP/AFoo.jar")
vec!.add("/dev/testSSCP/BFoo.jar")
env!.setClasspath("test", vec!)
print env!.getClasspath("test")

...Using an SSCP at the Command Line

In BBj 9.0 and later, the command line option -CPclasspathName specifies which SSCP to use when starting a BBj session. To run the program ATest.bbj using the SSCP whose name is test, use the command line:

bbj –CPtest Atest.bbj

...Using an SSCP with BBjAPI::newBBjSession()

An SSCP is used within the BBjAPI by using code similar to the following:

config! = BBjAPI().getConfig()
cmd! = config!.getCommandLineObject()
cmd!.setClasspathName("t")
x = BBjAPI().newBBjSession(cmd!)

Using an SSCP with BBjCpl

To compile and type-check programs that refer to jar files in a SSCP, BBjCpl also accepts a -CPclasspathName option. BBjCpl will use the SSCP configured via either BBjAPI or Enterprise Manager to search for Java class names when compiling and type-checking BBj programs. The following example will type-check the program Atest.bbj without producing any output:

bbjcpl -CPtest -N -X Atest.bbj

Modifying an Existing SSCP

Once a BBj session is started with a particular SSCP, then any changes made to that SSCP will not affect the running BBj session. This is illustrated in the following code that defines an SSCP named test, then starts a BBj session. After starting the BBj session, the SSCP changes, but the BBj session that has already started will not see the changes.

admin! = BBjAPI().getAdmin("admin","admin123")
config! = BBjAPI().getConfig()
env! = admin!.getEnvironment()
rem set the test SSCP
vec! = BBjAPI().makeVector()
vec!.add("/dev/testSSCP/AFoo.jar")
vec!.add("/dev/testSSCP/BFoo.jar")
env!.setClasspath("test", vec!)
rem retrieve a CommandLineObject and set its SSCP
cmd! = config!.getCommandLineObject()
cmd!.setClasspathName("TEST")
rem start a new BBjSession with the TEST SSCP
x = BBjAPI().newBBjSession(cmd!)
rem ==================================
rem modify the tests SSCP
rem the changes in test do NOT affect the program
rem that has already been started
rem ==================================
vec!.add("/dev/testSSCP/CFoo.jar")
env!.setClasspath("test", vec!)

Modifying Jar Files and Reloading an SSCP

If a jar file named  foo.jar is contained in an SSCP named test and foo.jar is modified on disk then there are several factors that determine whether a BBjSession that is using the test SSCP will recognize the changes in foo.jar (i.e. whether files will be loaded from the old foo.jar or the newly modified foo.jar).

These factors include:

  • Whether a program calls BBjEnvironment::reloadClasspath(“test”)

  • How the ‘recheck session classpath’ performance setting in Enterprise Manager was set

  • If the BBj session was started before or after the change was made

If any program invokes the method BBjEnvironment::reloadClasspath("test"), then all subsequent BBj processes that use the test SSCP will load classes from the modified jar. It is best to call this method after modifying any jar file that is on any SSCP.

If Recheck Session Classpath is set to “development,” then BBj checks the date of each file on the SSCP every time a new BBj process is started with that SSCP. This means that any new BBj process that use test SSCP will load classes from the modified jar.

The behavior of BBj sessions that were already running prior to changing foo.jar is system dependent. We recommend that jar files not be modified until all BBj processes that are using a SSCP that includes that jar file are terminated.

SSCP and Static Variables

In Java, a static variable is shared across all instances of a given class. In most cases there is only one class for any given class name within the entire JVM so a static variable is shared across the entire JVM. When using SSCP, this is not always the case. If Foobar.class is found in foo.jar, and foo.jar appears in two different SSCPs named testA and testB, then each SSCP will load a different class object for Foobar. This means that the code running within a BBj session with testA SSCP will have a different class object for Foobar than the code running in a BBj session with testB SSCP. Those BBj sessions will see a different value for any static variable that is in Foobar.

Similarly, if a call is made to BBjEnvironment::reloadClasspath("testA"), then any new BBj sessions that use the testA SSCP will see a different static variable than any BBj sessions that were started with the testA SSCP before the call to reloadClasspath().

SSCP and BASIS Jars

BBj ships with a number of jar files, some of which BBjServices require and some the various demo programs use. The jars that BBjServices require cannot be overridden by jars in an SSCP. These jars are included in the BBjIndex.jar which is included on BBjServices’ classpath. Any class found in a jar on an SSCP will not be loaded if it shares its class name with another class that is found in a jar that BBj requires.

SSCP and the BBjServices Classpath

Classes that are found in jars on an SSCP will override classes that are found in the other jars on the BBjServices classpath, including those indexed with ExtIndex.jar but not those indexed with BBjIndex.jar. This means that if a class found in a jar on the SSCP has the same class name as a class found in a non-required jar that is on the BBjServices classpath, then BBj will use the class from the SSCP.

NOTE: Some third party jars used by BBj cannot be overridden in a session-specific classpath. These jars are indexed with BBjIndex.jar.

Identifying Jars/Classes that are not overrridable with SSCP

The classes in the jars indexed by BBjIndex.jar are not overridable with SSCP. To see a list of these jars and the packages they contain, extract the META-INF/INDEX.LIST from the BBjIndex.jar. The following command can be used to extract this file:

> jar xf ${BBjHome}/lib/BBjIndex.jar META-INF/INDEX.LIST

After running the command, the extracted META-INF/INDEX.LIST has entries that look like this:

BasisCharsetProvider.jar
META-INF
META-INF/services
com
com/basis
com/basis/util

Each jar listed is followed by the packages contained within that jar. To see more details on the classes in the jar, use the following command:

> jar tf ${BBjHome}/lib/BasisCharsetProvider.jar
META-INF/MANIFEST.MF
META-INF/
com/
com/basis/
com/basis/util/
com/basis/util/BasisCharsetProvider$BasisCharset.class
com/basis/util/BasisCharsetProvider$BasisCharsetDecoder.class
com/basis/util/BasisCharsetProvider$BasisCharsetEncoder.class
com/basis/util/BasisCharsetProvider.class
META-INF/services/
META-INF/services/java.nio.charset.spi.CharsetProvider
META-INF/BASIS.KEY

This command lists all the classes included in the jar.



______________________________________________________________________________________

Copyright BASIS International Ltd. BBj®, Visual PRO/5®, PRO/5®, and BBx® are registered trademarks.