Oracle8i Java Developer's Guide Release 3 (8.1.7) Part Number A83728-01 |
Library | Service | Contents | Index

## Preparing Java Class Methods for Execution

For your Java methods to be executed, you must do the following:

1. Decide when your source is going to be compiled.

2. Decide if you are going to use the default resolver or another resolver for locating supporting Java classes within the database.

3. Load the classes into the database. If you do not wish to use the default resolver for your classes, you should specify a separate resolver on the load command.

4. Publish your class or method.

### Compiling Java Classes

Compilation of your source can be performed in one of the following ways:

- You can compile the source explicitly on your client machine before loading it into the database through a Java compiler, such as `javac`.

- You can ask the database to compile the source during the loading process managed within the `loadjava` tool.

- You can force the compilation to occur dynamically at runtime.

  Note: If you decide to compile through `loadjava`, you can specify compiler options. See "Specifying Compiler Options" for more information.

#### Compiling Source through javac

You can compile your Java with a conventional Java compiler, such as `javac`. After compilation, you load the compiled binary into the database, rather than the source itself. This is a better option, because it is normally easier to debug your Java code on your own system, rather than debugging it on the database.

#### Compiling Source through loadjava

When you specify the -`resolve` option on `loadjava` for a source file, the following occurs:

1. The source file is loaded as a source schema object.

2. The source file is compiled.

3. Class schema objects are created for each class defined in the compiled `.java` file.

4. The compiled code is stored in the class schema objects.

JServer logs all compilation errors both to `loadjava`'s logfile and the `USER_ERRORS` view. For more information on the `USER_ERRORS` view, see the Oracle8i Reference for a description of this table.

#### Compiling Source at Runtime

When you load the Java source into the database without the -`resolve` option, JServer compiles the source automatically when the class is needed during runtime. The source file is loaded into a source schema object.

JServer logs all compilation errors both to `loadjava`'s logfile and the `USER_ERRORS` view. For more information on the `USER_ERRORS` view, see the Oracle8i Reference for a description of this table.

#### Specifying Compiler Options

There are two ways to specify options to the compiler.

- Specify compiler options on the `loadjava` command line. You can specify the `encoding` option on the `loadjava` command line.

- Specify persistent compiler options in a per-schema database table called `JAVA$OPTIONS`. Every time you compile, the compiler uses these options. However, any specified compiler options on the `loadjava` command override the options defined in this table.

  You must create this table yourself if you wish to specify compiler options this way. See "Compiler Options Specified in a Database Table" for instructions to create the `JAVA$OPTIONS` table.

The following sections describe your compiler options:

- Default Compiler Options

- Compiler Options on the Command Line

- Compiler Options Specified in a Database Table

##### Default Compiler Options

When compiling a source schema object for which there is neither a `JAVA$OPTIONS` entry nor a command line value for an option, the compiler assumes a default value as follows:

- `encoding` = `latin1`

- `online` = `true`: See the Oracle8i SQLJ Developer's Guide and Reference for a description of this option, which applies only to Java sources that contain SQLJ constructs.

- `debug` = `true`: This option is equivalent to `javac` `-g`.

##### Compiler Options on the Command Line

The `loadjava` compiler option, `encoding`, identifies the encoding of the `.java` file. This option overrides any matching value in the `JAVA$OPTIONS` table. The values are identical to the `javac` `-encoding` option. This option is relevant only when loading a source file.

##### Compiler Options Specified in a Database Table

Each `JAVA$OPTIONS` row contains the names of source schema objects to which an option setting applies; you can use multiple rows to set the options differently for different source schema objects.

You can set `JAVA$OPTIONS` entries by means of the following functions and procedures, which are defined in the database package `DBMS_JAVA`:

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

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

- `PROCEDURE reset_compiler_option(name VARCHAR2, option VARCHAR2);`

The parameters for these methods are described below:

Parameter | Description
--- | ---
name | The `name` parameter is a Java package name, a fully qualified class name, or the empty string. When the compiler searches the `JAVA$OPTIONS` table for the options to use for compiling a Java source schema object, it uses the row whose `name` most closely matches the schema object's fully qualified class name. A `name` whose value is the empty string matches any schema object name.
option | The `option` parameter is either `'online'`, `'encoding'` or `'debug'`. For the `value`s you can specify for these options, see the Oracle8i SQLJ Developer's Guide and Reference

.

A schema does not initially have a `JAVA$OPTIONS` table. To create a `JAVA$OPTIONS` table, use the `DBMS_JAVA` package's `java.set_compiler_option` procedure to set a value. The procedure will create the table if it does not exist. Specify parameters in single quotes. For example:

    SQL> execute dbms_java.set_compiler_option('x.y', 'online', 'false');

Table 2-1 represents a hypothetical `JAVA$OPTIONS` database table. The pattern match rule is to match as much of the schema name against the table entry as possible. The schema name with a higher resolution for the pattern match is the entry that applies. Because the table has no entry for the `encoding` option, the compiler uses the default or the value specified on the command line. The `online` option shown in the table matches schema object names as follows:

- The name `a.b.c.d` matches class and package names beginning with `a.b.c.d`; the packages and classes are compiled with `online` = `true`.

- The name `a.b` matches class and package names beginning with `a.b`. The name `a.b` does not match `a.b.c.d`; therefore, the packages and classes are compiled with `online` = `false`.

- All other packages and classes match the empty string entry and are compiled with `online` = `true`.

  ##### Table 2-1 Example JAVA$OPTIONS Table

  JAVA$OPTIONS Entries | Match Examples
  --- | ---
  Name | Option | Value
  `a.b.c.d` | `online` | `true` | `a.b.c.d`--matches the pattern exactly. `a.b.c.d.e`--first part matches the pattern exactly; no other rule matches full name.
  `a.b` | `online` | `false` | `a.b`--matches the pattern exactly `a.b.c.x`--first part matches the pattern exactly; no other rule matches beyond specified rule name.
  (empty string) | `online` | `true` | `a.c`--no pattern match with any defined name; defaults to (empty string) rule `x.y`--no pattern match with any defined name; defaults to (empty string) rule

#### Automatic Recompilation

JServer provides a dependency management and automatic build facility that will transparently recompile source programs when you make changes to the source or binary programs upon which they depend. Consider the following cases:

    public class A
    {
          B b;
          public void assignB () {b = new B()}
    }
    public class B
    {
          C c;
          public void assignC () {c = new C()}
    }
    public class C
    {
          A a;
          public void assignA () {a = new A()}
    }

The system tracks dependencies at a class level of granularity. In the preceding example, you can see that classes A, B, and C depend on one another, because A holds an instance of B, B holds an instance of C, and C holds an instance of A. If you change the definition of class A by adding a new field to it, the dependency mechanism in Oracle8i flags classes B and C as invalid. Before you use any of these classes again, Oracle8i attempts to resolve them again and recompile, if necessary. Note that classes can be recompiled only if source is present on the server.

The dependency system enables you to rely on Oracle8i to manage dependencies between classes, to recompile, and to resolve automatically. You must only force compilation and resolution yourself only if you are developing and you want to find problems early. The `loadjava` utility also provides the facilities for forcing compilation and resolution if you do not want to allow the dependency management facilities to perform this for you.

### Resolving Class Dependencies

Many Java classes contain references to other classes, which is the essence of reusing code. A conventional Java virtual machine searches for classes, ZIP, and JAR files within the directories specified in the CLASSPATH. In contrast, the Aurora Java virtual machine searches database schemas for class objects. With Oracle8i, you load all Java classes within the database, so you might need to specify where to find the dependent classes for your Java class within the database.

All classes loaded within the database are referred to as class schema objects and are loaded within certain schemas. All JVM classes, such as `java.lang.*`, are loaded within `PUBLIC`. If your classes depend upon other classes you have defined, you will probably load them all within your own schema. For example, if your schema is `SCOTT`, the database resolver (the database replacement for `CLASSPATH`) searches the `SCOTT` schema before `PUBLIC`. The listing of schemas to search is known as a resolver spec. Resolver specs are per-class, whereas in a classic Java virtual machine, CLASSPATH is global to all classes.

When locating and resolving the interclass dependencies for classes, the resolver marks each class as valid or invalid, depending on if all interdependent classes are located or not. If the class that you load contains a reference to a class that is not found within the appropriate schemas, the class is listed as invalid. Unsuccessful resolution at runtime produces a "class not found" exception. Furthermore, runtime resolution can fail for lack of database resources if the tree of classes is very large.

Note: As with the Java compiler, `loadjava` resolves references to classes, but not to resources. Be sure to correctly load the resource files your classes need.

For each interclass reference in a class, the resolver searches the schemas specified by the resolver spec for a valid class schema object that satisfies the reference. If all references are resolved, the resolver marks the class valid. A class that has never been resolved, or has been resolved unsuccessfully, is marked invalid. A class that depends on a schema object that becomes invalid is also marked invalid.

To make searching for dependent classes easier, Oracle8i provides a default resolver and resolver spec that searches first the definer's schema and then PUBLIC. This covers most of the classes loaded within the database. However, if you are accessing classes within a schema other than your own or PUBLIC, you must define your own resolver spec.

- loading using Oracle's default resolver, which searches the definer's schema and `PUBLIC`:

      loadjava -resolve

- loading using your own resolver spec definition containing the SCOTT schema, OTHER schema, and PUBLIC:

      loadjava -resolve -resolver "((* SCOTT)(* OTHER)(* PUBLIC))"

The -`resolver` option specifies the objects to search within the schemas defined. In the example above, all class schema objects are searched within SCOTT, OTHER, and PUBLIC. However, if you wanted to search for only a certain class or group of classes within the schema, you could narrow the scope for the search. For example, to search only for the classes "`my/gui/*"` within the OTHER schema, you would define the resolver spec as follows:

    loadjava -resolve -resolver '((* SCOTT) ("my/gui/*" OTHER) (* PUBLIC))'

The first parameter within the resolver spec is for the class schema object; the second parameter defines the schema to search for these class schema objects.

#### Allowing References to Non-Existent Classes

You can specify a special option within a resolver spec that allows an unresolved reference to a non-existent class. Sometimes, internal classes are never used within a product. For example, some ISVs do not remove all references to internal test classes from the JAR file before shipping. In a normal Java environment, this is not a problem, because as long as the methods are not called, Sun Microsystems's JVM ignores them. However, the Oracle8i resolver tries to resolve all classes referenced within the JAR file--even unused classes. If the reference cannot be validated, the classes within the JAR file are marked as invalid.

To ignore references, you can specify the "-" wildcard within the resolver spec. The following example specifies that any references to classes within "`my/gui`" are to be allowed even if it is not present within the resolver spec schema list.

    loadjava -resolve -resolver '((* SCOTT) (* PUBLIC) ("my/gui/*" -))'

In addition, you can define that all classes not found are to be ignored. Without the wildcard, if a dependent class is not found within one of the schemas, your class is listed as invalid and cannot be run. However, this is also dangerous, because if there is a dependent class on a used class, you mark a class as valid that can never run without the dependent class. In this case, you will receive an exception at runtime.

To ignore all classes not found within SCOTT or PUBLIC, specify the following resolver spec:

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

Note: Never use a resolver containing "-" if you later intend to load the classes that were causing you to use such a resolver in the first place. Instead, include all referenced classes in the schema before resolving.

#### ByteCode Verifier

According to the JVM specification, `.class` files are subject to verification before the class they define is available in a JVM. In JServer, the verification process occurs at class resolution. The resolver might find one of the following problems and issue the appropriate Oracle error code:

ORA-29545 | If the resolver determines that the class is malformed, the resolver does not mark it valid. When the resolver rejects a class, it issues an ORA-29545 error (badly formed class). The `loadjava` tool reports the error. For example, this error is thrown if the contents of a `.class` file are not the result of a Java compilation or if the file has been corrupted.
ORA-29552 | In some situations, the resolver allows a class to be marked valid, but will replace bytecodes in the class to throw an exception at runtime. In these cases, the resolver issues an ORA-29552 (verification warning), which `loadjava` will report. The `loadjava` tool issues this warning when the Java Language Specification would require an `IncompatibleClassChangeError` be thrown. JServer relies on the resolver to detect these situations, supporting the proper runtime behavior the JLS requires.

The resolver also issues warnings, as defined below:

- Resolvers containing "-"

  This type of resolver marks your class valid regardless of whether classes it references are present. Because of inheritance and interfaces, you might want to write valid Java methods that use an instance of a class as if it were an instance of a superclass or of a specific interface. When the method being verified uses a reference to class A as if it were a reference to class B, the resolver must check that A either extends or implements B. For example, consider the potentially valid method below, whose signature implies a return of an instance of B, but whose body returns an instance of A:

      B myMethod(A a) { return a; }

  The method is valid only if A extends B or A implements the interface B. If A or B have been resolved using a "-" term, the resolver does not know that this method is safe. It will replace the bytecodes of `myMethod` with bytecodes that throw an Exception if `myMethod` is ever called.

- Use of other resolvers``

  The resolver ensures that the class definitions of A and B are found and resolved properly if they are present in the schemas they specifically identify. The only time you might consider using the alternative resolver is if you must load an existing JAR file containing classes that reference other non-system classes not included in the JAR file.

For more information on class resolution and loading your classes within the database, see the Oracle8i Java Tools Reference.

### Loading Classes

This section gives an overview of the main points you should understand when loading your classes into the database. It discusses various options for the `loadjava` tool, but does not go into all the details. You can also execute `loadjava` within your SQL. See the Oracle8i Java Tools Reference for complete information on `loadjava`.

Unlike a conventional Java virtual machine, which compiles and loads from files, the Aurora Java virtual machine compiles and loads from database schema objects.

.`java` source files or .`sqlj` source files | correspond to Java source schema objects
.`class` compiled Java files | correspond to Java class schema objects
.`properties` Java resource files, .`ser` SQLJ profile files, or data files | correspond to Java resource schema objects

You must load all classes or resources into the database to be used by other classes within the database. In addition, at loadtime, you define who can execute your classes within the database.

The `loadjava` tool performs the following for each type of file:

Schema object | `loadjava` operations on object
.`java` source files | It creates a source schema object within the definer's schema unless another schema is specified It loads the contents of the source file into a schema object It creates a class schema objects for all classes defined in the source file If -`resolve` is requested, it does the following: a. It compiles the source schema object b. It resolves the class and its dependencies c. It stores the compiled class into a class schema object
.`sqlj` source files | It creates a source schema object within the definer's schema unless another schema is specified It loads contents of the source file into the schema object It creates a class schema objects for all classes and resources defined in the source file If -`resolve` is requested, it does the following: a. It translates and compile the source schema object b. It stores the compiled class into a class schema object c. It stores profile into .`ser` resource schema object and customizes it
.`class` compiled Java files | It creates a class schema object within the definer's schema unless another schema is specified It loads the class file into the schema object It resolves and verify the class and its dependencies if -`resolve` is specified
.`properties` Java resource files | It creates a resource schema object within the definer's schema unless another schema is specified It loads resource file into a schema object
.`ser` SQLJ profile | It creates a resource schema object within the definer's schema unless another schema is specified It loads .`ser` resource file into a schema object and customizes it

The `dropjava` tool performs the reverse of the `loadjava` tool: it deletes schema objects that correspond to Java files. You should always use `dropjava` to delete a Java schema object created with `loadjava`. Dropping with SQL DDL commands will not update auxiliary data maintained by `loadjava` and `dropjava`. You can also execute `dropjava` from within SQL commands.

Note: More options for `loadjava` are available. However, this section discusses only the major options. See the Oracle8i Java Tools Reference for complete information on `loadjava` and `dropjava`.

You must abide by certain rules when loading classes into the database, which are detailed in the following sections:

- Two Definitions of the Same Class

- Need Database Privileges and JVM Permissions

- Loading JAR or ZIP Files

After loading, you can access the `USER_OBJECTS` view in your database schema to verify that your classes and resources loaded properly. For more information, see "Checking Java Uploads".

#### Two Definitions of the Same Class

You cannot have two different definitions for the same class. This rule affects you in two ways:

- You can load either a particular Java .`class` file or its .`java` file, but not both.

  JServer tracks whether you loaded a class file or a source file. If you wish to update the class, you must load the same type of file that you originally loaded. If you wish to update the other type, you must drop the first before loading the second. For example, if you loaded `x.java` as the source for class `y`, to load `x.class`, you must first drop `x.java`.

- You cannot define the same class within two different schema objects within the same schema. For example, suppose `x.java` defines class `y` and you want to move the definition of `y` to `z.java`. If `x.java` has already been loaded, `loadjava` rejects any attempt to load `z.java` (which also defines `y`). Instead, do either of the following:

  - Drop `x.java`, load `z.java` (which defines `y`), then load the new `x.java` (which does not define `y`).

  - Load the new `x.java` (which does not define `y`), then load `z.java` (which defines `y`).

#### Need Database Privileges and JVM Permissions

You must have the following SQL database privileges to load classes:

- `CREATE` `PROCEDURE` and `CREATE TABLE` privileges to load into your schema.

- `CREATE` `ANY` `PROCEDURE` and `CREATE ANY TABLE` privileges to load into another schema.

- oracle.aurora.security.JServerPermission.loadLibraryInClass.<classname>. See "Permission for Loading Classes" for more information.

#### Loading JAR or ZIP Files

The `loadjava` tool accepts .`class`, .`java`, .`properties,` .`sqlj`, .`ser`, .`jar`, or .`zip` files. The JAR or ZIP files can contain source, class, and data files. When you pass `loadjava` a JAR or ZIP file, `loadjava` opens the archive and loads its members individually. There is no JAR or ZIP schema object. If the JAR or ZIP content has not changed since the last time it was loaded, it is not reloaded; therefore, there is little performance penalty for loading JAR or ZIP files. In fact, loading JAR or ZIP files is the simplest way to use `loadjava`.

Note: JServer does not reload a class if it has not changed since the last load. However, you can force a class to be reloaded through the `loadjava -force` option.

### How to Grant Execute Rights

When you are loading your classes, you can grant execution rights to another user through an option for loadjava. There are two methods for defining who can execute your class:

- granting execution rights to a certain user or schema

  The classes that define a Java application are stored within the Oracle8i RDBMS under the SQL schema of their owner. By default, classes that reside in one user's schema are not executable by other users, because of security concerns. You can allow other users (schemas) the right to execute your class through the `loadjava -grant` option.

- specifying what user or schema is evaluated for the execution rights to the class

  You can specify that the user evaluated for execution rights is either the invoker or the definer. Invoker's and definer's rights are SQL concepts that are applicable to your Java classes. In SQL, when you execute under definer's rights, you execute with the user identifier for the schema that loaded the PL/SQL. With invoker's rights, your SQL executes with the user identifier for the schema that actually invokes the PL/SQL. This applies to the Java classes in that the schema that is evaluated for JVM security permission to execute is based on whether the class was loaded under invoker's or definer's rights.

#### Figure 2-2 Invoker's Versus Definer's Rights

With the example in Figure 2-2, which class, A or B, is checked when the method in class C is executed? This depends on invoker's or definer's rights.

- Invoker's rights--By default, classes run under the effective identity and rights of the client's schema that initially invokes the method in C. In this case, the rights for class A is checked. Because class A does not have permission to execute C, the request is rejected. This is the default.

- Definer's rights--Classes execute under the effective identity of the user that loaded the class. If, when you loaded class B, you specified definer's rights, class B is checked when the method in class C is invoked. Because class B has the right to execute methods in class C, the method completes successfully. Class B is loaded with definer's rights by executing `loadjava -definer`.

For information on JVM security permissions, see Chapter 6, "Oracle8i Java Application Performance".

### Checking Java Uploads

You can query the database view `USER_OBJECTS` to obtain information about schema objects--including Java sources, classes, and resources--that you own. This allows you, for example, to verify that sources, classes, or resources that you load are properly stored into schema objects.

Columns in `USER_OBJECTS` include those contained in Table 2-2 below.

##### Table 2-2 Key USER_OBJECT Columns

Name | Description
--- | ---
OBJECT_NAME | name of the object
OBJECT_TYPE | type of the object (such as `JAVA SOURCE`, `JAVA CLASS`, or `JAVA RESOURCE`)
STATUS | status of the object (`VALID` or `INVALID`) (always `VALID` for `JAVA RESOURCE`)

#### Object Name and Type

An `OBJECT_NAME` in `USER_OBJECTS` is the short name. The full name is stored as a short name if it exceeds 31 characters. See "Shortened Class Names" for more information on full and short names.

If the server uses a short name for a schema object, you can use the `LONGNAME()` routine of the server `DBMS_JAVA` package to receive it from a query in full name format, without having to know the short name format or the conversion rules.

    SQL*Plus> SELECT dbms_java.longname(object_name) FROM user_objects
              WHERE object_type='JAVA SOURCE';

This routine shows you the Java source schema objects in full name format. Where no short name is used, no conversion occurs, because the short name and full name are identical.

You can use the `SHORTNAME()` routine of the `DBMS_JAVA` package to use a full name as a query criterion, without having to know whether it was converted to a short name in the database.

    SQL*Plus> SELECT object_type FROM user_objects
              WHERE object_name=dbms_java.shortname('known_fullname');

This routine shows you the `OBJECT_TYPE` of the schema object of the specified full name. This presumes that the full name is representable in the database character set.

    SVRMGR> select * from javasnm;
    SHORT                          LONGNAME
    ----------------------------------------------------------------------
    /78e6d350_BinaryExceptionHandl sun/tools/java/BinaryExceptionHandler
    /b6c774bb_ClassDeclaration     sun/tools/java/ClassDeclaration
    /af5a8ef3_JarVerifierStream1   sun/tools/jar/JarVerifierStream$1

#### Status

`STATUS` is a character string that indicates the validity of a Java schema object. A source schema object is `VALID` if it compiled successfully; a class schema object is `VALID` if it was resolved successfully. A resource schema object is always `VALID,` because resources are not resolved.

##### Example: Accessing USER_OBJECTS

The following `SQL*Plus` script accesses the `USER_OBJECTS` view to display information about uploaded Java sources, classes, and resources.

    COL object_name format a30
    COL object_type format a15
    SELECT object_name, object_type, status
       FROM user_objects
       WHERE object_type IN ('JAVA SOURCE', 'JAVA CLASS', 'JAVA RESOURCE')
       ORDER BY object_type, object_name;

You can optionally use wildcards in querying `USER_OBJECTS`, as in the following example.

    SELECT object_name, object_type, status
       FROM user_objects
       WHERE object_name LIKE '%Alerter';

This routine finds any `OBJECT_NAME` entries that end with the characters: `Alerter`.

For more information about `USER_OBJECTS`, see the Oracle8i Java Stored Procedures Developer's Guide.

### Publishing

Oracle8i enables clients and SQL to invoke Java methods loaded within the database, once published. You publish either the object itself or individual methods, depending on the type of Java application it is, as shown below:

Java API | Publishing method | Reference
--- | --- | ---
Java stored procedures | If you write a Java stored procedure that you intend to invoke with a trigger, directly or indirectly in SQL DML or in PL/SQL, you must publish individual methods within the class. You specify how to access it through a call specification. Java programs consist of many methods in many classes; however, only a few static methods are typically exposed with call specifications. | Oracle8i Java Stored Procedures Developer's Guide

.

Servlet and JavaServer Pages

Publish the servlet and JavaServer Pages URL within the JNDI namespace.

Oracle8i Oracle Servlet Engine User's Guide

Oracle JavaServer Pages Developer's Guide and Reference

CORBA and EJB development

You do not use call specifications for CORBA or EJB objects. Instead, you publish the object reference for the client to retrieve. Once the object is retrieved, the client can invoke specific methods within the object.

Oracle8i's CORBA and EJB implementations support standard CORBA and Java styles of exposing objects by name, with accompanying CORBA and Java-style specifications of the interfaces to those objects.

- You publish CORBA IOR's through the `publish` tool.

- You publish EJB Home and Remote interfaces through the `deployejb` tool.

Oracle8i Enterprise JavaBeans Developer's Guide and Reference or the Oracle8i CORBA Developer's Guide and Reference books

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