Deploying Cloudscape Applications
Page 4 of 4

Loading Classes from a Database

You can store application logic in a database and then load classes from the database. Application logic, which can be used by both Cloudscape (for database-side methods and stored objects) and your application, includes Java class files and other resources. Storing application code simplifies application deployment, since it reduces the potential for problems with a user's class path.

In an embedded environment, when application logic is stored in the database, both the user application and Cloudscape can access classes loaded by the Cloudscape class loader from stored jar files.

NOTE: You can publish stored classes in a synchronized system. For more information about publishing stored classes, see the Cloudscape Synchronization Guide.

Class Loading Overview

You store application classes and resources by storing one or more jar files in the database. Then your application can access classes loaded by Cloudscape from the jar file and does not need to be coded in a particular way. The only difference is the way in which you invoke the application. Here are the basic steps:

  1. Create Jar Files for Your Application
  2. Choose Between Database-Level and System-Level Class Loading
  3. Add the Jar File or Files to the Database
  4. Enable Database Class Loading with a Property
  5. Force Cloudscape Class Loading for the Application
  6. Code Your Applications the Way You Normally Would

NOTE: If you are interested in making changes to jar files stored in the database or changing the database jar "class path" of your application without having to re-boot, read Dynamic Changes to Jar Files or Database Jar Class Path.

Signed Jar Files

For information about how Cloudscape handles signed jar files, see Signed Jar Files

Create Jar Files for Your Application

Include any Java classes in a jar file intended for Cloudscape class loading except:

  • the standard Java packages (java.*, javax.*)

    Cloudscape does not prevent you from storing such a jar file in the database, but these classes are never loaded from the jar file.

  • those supplied with your Java environment (for example, sun.*)

A running Cloudscape system can load classes from any number of jar files from any number of schemas and databases.

Create jar files intended for Cloudscape database class loading the same way you create a jar file for inclusion in a user's class path. For example:

jar cf tours.jar JBMSTours\*.class

Various IDEs have tools to generate a list of contents for a jar file based on your application. If your application requires classes from other jar files, you have a choice:

  • Extract the required third-party classes from its jar file and include only those in your jar file.

    Best if you need only a small subset of the classes in the third-party jar file.

  • Store the third-party jar file in the database.

    Best if you need most or all of the classes in the third-party jar file, since your application and third-party logic can be upgraded separately.

  • Deploy the third-party jar file in the user's class path.

    Best if the classes are often already installed on a user's machine (for example, Objectspace's JGL classes).

Include the class files and resources needed for your application.

Choose Between Database-Level and System-Level Class Loading

  • Database-level class loading

    You can store jar files in a single database and make those jar files available to that database only. This is the recommended practice, as it allows publication of jar files in synchronized systems and makes it possible to make changes to jar files or to change the database jar "class path" dynamically (without having to reboot).

  • System-level class loading

    You can also store jar files in any database or databases in the system and make those jar files available to all databases in the system. This usage is not possible when user authentication is turned on, because the system does not provide a user name and password when loading the class from the database where the jar file is stored.

    Note that it is possible to have system class loading in general but database class loading in a particular database.

    With system-level class loading, if you make changes to jar files or change the database jar "class path", you will have to reboot to see the effects of those changes.

Add the Jar File or Files to the Database

Use the COM.cloudscape.tools.dbclasses utility (aliased as dbclasses) to add, update, and remove jar files in a database. When you add a jar file to a database, you give it a Cloudscape jar name, which is an SQL92Identifier.

See the Cloudscape Tools and Utilities Guide for reference information about the utility.

NOTE: Once a jar file has been stored, you cannot modify any of the individual classes or resources within the jar file. Instead, you must replace the entire jar file.

NOTE: Adding, removing, or replacing a jar file invalidates all stored prepared statements in the database.

You can use the utility on the command line or within an SQL-J statement. On the command line, you delimit the Cloudscape jar name with the schema name if it is not the default (APP). Within an SQL-J statement, you supply the schema name as a parameter to the method separately.

Examples

See the Cloudscape Tools and Utilities Guide for reference information about the utility and complete syntax.

Adding Jar Files

-- SQL-J statement
CALL dbclasses.addJar(
    'APP', 'ToursLogic', 'tours.jar')

-- SQL-J statement
-- using a quoted identifier for the Cloudscape jar name
CALL dbclasses.addJar(
    'APP', '"ToursLogic!"', 'tours.jar')

-- from the command line
java COM.cloudscape.tools.dbclasses add jdbc:cloudscape:toursDB
    APP.ToursLogic tours.jar

-- SQL-J statement
-- using a quoted identifier for the Cloudscape jar name
-- on the command line you need to escape double quotes
java COM.cloudscape.tools.dbclasses add jdbc:cloudscape:toursDB
    APP.\"ToursLogic!\" tours.jar

Removing Jar Files

-- SQL-J statement
CALL dbclasses.removeJar(
    'APP', 'ToursLogic')

-- from the command line
java COM.cloudscape.tools.dbclasses remove
    jdbc:cloudscape:toursDB APP.ToursLogic

Replacing Jar Files

-- SQL-J statement
CALL dbclasses.replaceJar(
    'APP', 'ToursLogic', 'c:\myjarfiles\newtours.jar')

-- from the command line
java COM.cloudscape.tools.dbclasses replace
    jdbc:cloudscape:toursDB APP.ToursLogic
    c:\myjarfiles\newtours.jar

Enable Database Class Loading with a Property

Once you have added one or more jar files to a database, you must set the database jar "class path" by including the jar file or files in the cloudscape.database.classpath property to enable Cloudscape to load classes from the jar files. This property, which behaves like a class path, specifies the jar files to be searched for classes and resources and the order in which they are searched. If Cloudscape does not find a needed class stored in the database, it can retrieve the class from the user's class path. (Cloudscape first looks in the user's class path before looking in the database.)

Separate jar files with a colon (:).

  • Database-level class loading

    Use two-part names for the jar files (schema name and jar name). Set the property as a database-level property for the database. The first time you set the property, you must reboot to load the classes.

    Example:

    CALL PropertyInfo.setDatabaseProperty(
        'cloudscape.database.classpath',
        'APP.ToursLogic:APP.ACCOUNTINGLOGIC')

  • System-level class loading

    Use three-part names for the jar files (database name, schema name, and jar name). Set the property as a system property.

    Example: One jar file is in the photodb database with the Cloudscape name photo, the other in the general database with the Cloudscape name jgl.

    cloudscape.database.classpath=photodb.APP.photo:general.APP.jgl

See cloudscape.database.classpath in Tuning Cloudscape for more information about the property.

NOTE: Cloudscape's class loader looks first in the user's class path for any needed classes, and then in the database. To ensure class loading with the database class loader, remove classes from the class path.

Force Cloudscape Class Loading for the Application

Typically, in an embedded environment, you want both Cloudscape and the application to use classes loaded by the same class loader. However, you can choose to have only Cloudscape use classes loaded by the Cloudscape class loader, and have your application use those classes loaded by the JVM class loader from the class path.

To choose this option, you must understand the implications of using different class loaders for each. Remember Figure 3-5? It showed how both Cloudscape and the application use the same classes (those loaded by the JVM from the class path). Because they use the same classes, they can pass entire objects back and forth. When they use different class loaders, they use different classes, and therefore cannot pass entire objects back and forth.

Class Loading: Database-Side Only vs. Database- and Application-Side

You can do one of the following things:

  • enable Cloudscape class loading for database-side execution of code only, using standard JVM class loading for application-side execution of code from the user's class path

    This situation prevents the application and Cloudscape from passing entire objects back and forth; see Class Path Class Loading for Application-Side Logic Execution.

    In some stages of development, you may want this option.

NOTE: You can choose this option in a client/server scenario; however, the same limitations apply as in an embedded environment (described above).

  • enable Cloudscape class loading for database-side execution of code and for application-side execution of code

    This situation avoids any version mismatch, but requires that you invoke your application in a special way to force Cloudscape class loading (see Force Cloudscape Class Loading for the Application).

NOTE: You cannot choose this option in a client/server scenario.

Enabling Cloudscape Class Loading for Database-Side Logic Execution

Enabling Cloudscape loading for execution of database-side logic means that Cloudscape uses classes loaded by Cloudscape retrieved from stored jar files.

You automatically enable class loading for database-side logic execution by setting the cloudscape.database.classpath property (see Enable Database Class Loading with a Property).

Class Path Class Loading for Application-Side Logic Execution

Cloudscape does not automatically load classes from the database for use by the application. When Cloudscape does not load classes for use by the application, the client application uses classes loaded by the JVM from the user's class path, not those loaded by the Cloudscape class loader. This leads to potential ClassCastExceptions. If two different class loaders (in this case, the one used by Cloudscape and the one used by the class path class loader) load the same class, the JVM does not recognize them as the same class and will throw a ClassCastException if the application and Cloudscape attempt to pass entire objects back and forth.

Figure 3-11 Application-side logic loaded from the class path, database-side logic loaded from the database. If the application retrieves objects from Cloudscape or stores objects in the database, a ClassCastException results.

Allowing two different class loaders is acceptable when the application does not retrieve entire objects from, or store entire objects in, the database. That is, it does not use the setObject and getObject methods of JDBC to send or retrieve user-defined Java data types from the database. The application can work with objects in a Cloudscape database only as follows:

  • It does not retrieve entire objects using getObject, but only executes methods that returned standard data types.
  • it does not use setObject to store objects but instead uses the NEW constructor within a SQL-J statement to store objects. (It can use getObject and setObject to store and retrieve standard java.* objects.)

The following is an excerpt from an application that will generate a ClassCastException if embedded Cloudscape uses Cloudscape class loading but the application uses class path class loading, even if the copy of the class in the class path is identical to the one stored in the database:

ResultSet rs = s.executeQuery(
    "SELECT City FROM Cities WHERE city_id = 1");
while (rs.next()) {
    mycity = (JBMSTours.City) rs.getObject(1);
}

In a client/server environment, no error is generated if both the application and Cloudscape are using the same versions of the classes, because the object is serialized and re-created at the client with the application class.

Cloudscape Class Loading for Client-Side Logic Execution

In situations in which class path loading for client-side logic execution is not appropriate, enable Cloudscape class loading for the client application. Doing so ensures that all classes are loaded by the same class loader.

Figure 3-12 Both the application and Cloudscape loading classes from the database

Cloudscape provides an application bootstrap program that forces Cloudscape class loading for application-side logic. The program is called COM.cloudscape.util.DBClassLoad.

Typically, you would invoke your class like this:

java COM.cloudscape.util.DBClassLoad databaseConnectionURL
    yourclassname
classarguments

databaseConnectionURL refers to the database in which the classes are stored.

In cases when user authentication is turned on and you are using database-level class loading, you will probably not want to put the user name and password on the command line in the database connection URL. In that case, you can invoke the class like this:

  • Create a "wrapper" class. Don't store this one in the database.
  • In that wrapper class, ask the user to input his or her user name and password.
  • At this point, you have two choices. Do one of the following:

For more information, see the javadoc for COM.cloudscape.util.DBClassLoad.

Code Your Applications the Way You Normally Would

In your applications, you cause classes to be loaded the way you normally would:

  • indirectly referencing them in the code
  • directly using java.lang.Class.forName

In your applications, you load resources the way you normally would, using the standard java.lang.Class.getResourceAsStream, a mechanism that allows an application to access resources defined in the class path without knowing where or how they are stored.

You do not need to make any changes to the way code interacts with Cloudscape and its JDBC driver. An application can safely attempt to boot Cloudscape, even though it is already running, without any errors. Applications connect to Cloudscape in the usual manner.

NOTE: The method getResource is not supported.

Dynamic Changes to Jar Files or Database Jar Class Path

In some situations, you can see changes to a class dynamically. That is, when you add or replace a jar file within an SQL-J statement or change the database jar "class path" (the cloudscape.database.classpath property), Cloudscape is able to load the new classes right away without your having to reboot.

Requirements

Certain conditions must be met for this to be true:

If these requirements are not met, you will have to reboot to see the changes.

Notes

When you are changing the cloudscape.database.classpath property, all classes loaded from database jar files are reloaded, even for a jar file that hasn't changed.

Remember that the user's class path is searched first.

Any existing prepared statements will use the previously loaded classes unless they require class loading, in which case they will fail with a ClassNotFound error.

Cached objects do not match objects created with newly loaded classes. For example, an in-memory Customer object will not match a new Customer object if the Customer class has been reloaded, and it will raise a ClassCastException. The issues are the same as those discussed in Class Path Class Loading for Application-Side Logic Execution.