Oracle8i Java Stored Procedures Developer's Guide Release 2 (8.1.6) Part Number A81358-01 |
Library | Service | Contents | Index

## Managing Java Schema Objects

To manage Java schema objects, you use the command-line utilities `loadjava` and `dropjava`. You can write, compile, and partially test and debug Java stored procedures on the client side in popular Java IDEs. Then, you can use `loadjava` to upload the resulting Java source, class, and resource files into the Oracle database as schema objects. In addition, you can use `dropjava` to drop given Java source, class, and resource schema objects from your schema.

### What to Load

For a particular Java class, you can load either its source file or class file, but not both. If you create Java class files on the client side, you can use `loadjava` to upload them into the Oracle database. Alternatively, you can upload Java source files and let the JServer JVM compile them. In most cases, it is best to compile and debug programs on the client side, then upload the class files for final testing within the database.

Loading Java archives (JARs) or ZIP archives is the simplest way to use `loadjava`. Archives cannot be schema objects. Therefore, when passed a JAR or ZIP archive, `loadjava` loads the archived files individually. For efficiency, files not modified since the last time they were loaded are not reloaded.

Two objects in the same schema cannot define the same class. Suppose you define class `X` in file `A.java`, load the file, then move the definition of `X` to file `B.java`. An attempt to load `B.java` will fail because it redefines class `X`. Instead, either drop `A.java` or load a new version of it that no longer defines `X`, then load `B.java`.

### How External References Are Resolved

All the classes in a Java program must be loaded before its external references can be resolved. One reason for this requirement is that Java programs have multiple source files because the JDK and other client-side tools require a separate source file for each public class. Another reason is that classes often refer to each other, so name resolution is not possible until all the files have been loaded.

You can use `loadjava` to force early resolution. When you specify the option `-resolve`, `loadjava` uses the SQL `ALTER` `JAVA` `CLASS` ... `RESOLVE` statement to resolve external references in uploaded Java classes. All references must be resolved before you can use those classes. If you do not specify the option, Oracle executes the SQL `ALTER` `JAVA` statement implicitly at run time.

If all its references to other classes cannot be resolved, a class is marked invalid. At run time, attempts to load an invalid class throw a `ClassNotFound` exception, as required by the Java Language Specification.

#### CLASSPATH versus Resolver Spec

Java classes are loaded dynamically at run time. In Sun Microsystem's JDK, the class loader locates a class by searching sequentially through the list of directories specified by the environment variable `CLASSPATH`.

The JServer JVM uses a similar list known as a resolver spec, but instead of directories, it specifies SQL schemas. When the JVM searches for a class corresponding to a Java name, it searches the list of schemas sequentially until the Java schema object with that name is found. If no such object is found, it generates an error.

Each class has its own resolver spec. For example, the class `X` resolver spec lists the schemas to be searched for the classes referenced by `X`. A facility known as the resolver maintains reference lists. The resolver searches the listed schemas for valid class schema objects that resolve the references. If all references are resolved, the resolver marks the class valid; otherwise, it marks the class invalid. If a schema object becomes invalid, all its dependent classes are marked invalid.

#### Resolution Modes

You can run `loadjava` in the following three resolution modes:

- Load, then resolve: If you specify the option `-resolve`, `loadjava` uploads all classes listed on the command line, marks them invalid, and then resolves them. Use this mode when loading classes that refer to each other, or when reloading isolated classes. Any class that depends on classes not yet loaded remains marked invalid.

- Load and resolve: If you specify the option `-andresolve`, `loadjava` resolves each class as it is loaded. In general, this mode is not recommended, especially when used with a resolver spec that leaves unresolved classes marked valid.

- Defer resolution: If you specify neither `-resolve` nor `-andresolve`, `loadjava` loads files but does not compile or resolve them. Instead, files are compiled (if necessary) and resolved at run time. (The resolver runs automatically when the JVM tries to load a class marked invalid.) However, it is best to resolve classes before run time to learn of missing classes early.

Like a Java compiler, `loadjava` resolves references to classes but not to resources. So, make sure the resource files that your classes need are loaded correctly.

#### Kinds of Resolver Specs

The option `-resolver` binds a resolver spec to the class schema objects that `loadjava` creates or replaces. Alternatively, you can use the option `-oracleresolver` (the default) to bind a predefined resolver spec to class schema objects. In most cases, the predefined resolver spec will meet your needs.

A resolver spec lists one or more items, each consisting of a name spec and schema spec in the following format:

    "((name_spec schema_spec) [(name_spec schema_spec)] ...)"

A name spec is similar to a name in a Java import statement. It can be a Java class full name, a package name whose last part is the wildcard "`*`", or just that wildcard. However, the elements of a name spec must be separated by slashes, not periods. For example, the name spec `test/util/*` matches all class names that begin with `test.util.` The special name spec, "`*`", matches all class names.

A schema spec can be a schema name or the wildcard "`-`". The wildcard does not identify a schema; it tells the resolver not to mark a class invalid even if a reference cannot be resolved. (Without the wildcard "`-`" in a resolver spec, an unresolved reference invalidates the class and generates an error.) Use the wildcard "`-"` when a class refers to classes that you cannot (or choose not to) load. For example, JServer cannot run the methods of GUI classes.

When matching a schema object name with a name spec, the resolver searches the schemas specified by the schema spec. The resolver searches schemas in the order they are listed in the resolver spec. For example, the following resolver spec tells the the resolver to search for a reference in schema `SCOTT`, then in schema `PUBLIC`:

    -resolver "((* SCOTT) (* PUBLIC))"

If it cannot resolve the reference, the resolver marks the referring class invalid and generates an error. The resolver spec below tells the resolver to ignore missing classes in package `utils.gui`. So, if a reference to a class in package `utils.gui` is not resolved, the resolver marks the referring class valid and generates no error.

    -resolver "((* SCOTT) (* PUBLIC) (utils/gui/* -))"

To have the resolver ignore all classes not found in schema `SCOTT` or schema `PUBLIC`, specify the following resolver spec:

    -resolver "((* SCOTT) (* PUBLIC) (* -))"

### What the Digest Table Does

`loadjava` uses the hash table `JAVA$CLASS$MD5$TABLE` (called "digest table" from here on) to track the loading of Java schema objects into a given schema. (`MD5` refers to RSA Data Security's MD5 Message-Digest Algorithm, which does the hashing.) If you use `loadjava` to load a Java schema object, you must use `dropjava` to drop the object. Otherwise, the digest table is not updated properly. If that happens, specify the option `-force` to bypass the digest table lookup.

The digest table enables `loadjava` to skip files that have not changed since they were last loaded. This improves the performance of makefiles and scripts that invoke `loadjava` for a whole list of files.

`loadjava` detects unchanged files by maintaining a digest table in every schema. The digest table relates a file name to a digest, which is a hash of the file's content. Comparing digests computed for the same file at different times is a fast way to detect a change in the file's content.

For each file it processes, `loadjava` computes a digest of the file's content, then looks up the file name in the digest table. If there is a matching entry, `loadjava` does not load the file (because a corresponding schema object exists and is up to date). If you specify the option `-verbose`, `loadjava` shows you the results of its digest table lookups.

### How Compilation Is Done

Loading a source file creates or updates a Java source schema object and invalidates the class schema objects derived previously from that source file (because they were not compiled from the newly loaded source file). If the class schema objects do not exist, they are created.

To force compilation when you upload a source file, specify the `loadjava` option `-resolve` or `-andresolve`. `loadjava` displays messages inserted by the compiler into the system database table `USER_ERRORS`. For a description of this table, see the Oracle8i Reference.

#### Passing Options to the Compiler

There are two ways to pass options to the compiler. If you specify the option `-resolve` or `-andresolve` (which might trigger compilation), then you can specify compiler options on the `loadjava` command line. You can also set compiler option values in the database table `JAVA$OPTIONS` (called "options table" from here on). Then, you can selectively override those settings using `loadjava` command-line options.

A row in the options table contains the names of source schema objects to which an option setting applies. You can use multiple rows for different settings. The option `encoding` specifies a character-encoding scheme; the option `online` enables online semantics checking (of SQLJ sources only).

The compiler looks up options in the options table unless they are specified on the `loadjava` command line. A command-line value overrides and clears a matching entry in the options table. If there are no options-table entries or command-line values for the options, the compiler uses the following default values:

    encoding = latin1
    online = true

For the non-default values, see the Oracle8i SQLJ Developer's Guide and Reference.

You can get, set, and reset options-table entries using the following function and procedures, which are defined in the utility package `DBMS_JAVA`:

    FUNCTION get_compiler_option (
      name VARCHAR2,
      option VARCHAR2)
    RETURNS VARCHAR2;

    PROCEDURE set_compiler_option (
      name VARCHAR2,
      option VARCHAR2,
      value VARCHAR2);

    PROCEDURE reset_compiler_option (
      name VARCHAR2,
      option VARCHAR2);

The parameter `name` is the name of a Java package, the full name of a class, or the empty string. After searching the options table, the compiler selects the row in which `name` most closely matches the full name of the schema object. If `name` is the empty string, it matches the name of any schema object.

Initially, a schema does not have an options table. To create one, use the procedure `dbms_java.set_compiler_option` to set a value. The procedure creates the table if it does not exist. Enclose parameters in single quotes, as shown in the following example:

    SQL> dbms_java.set_compiler_option('X.sqlj', 'online', 'false');

For more information about package `DBMS_JAVA`, see the Oracle8i Java Developer's Guide.

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index