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

# 1
Introduction

The Oracle JServer has all the features you need to build a new generation of enterprise-wide applications at low cost. Chief among those features are stored procedures, which open the Oracle RDBMS to all Java programmers. With stored procedures, you can implement business logic at the server level, thereby improving application performance, scalability, and security.

#### Major Topics

- Java and the RDBMS: A Robust Combination

- Stored Procedures and Run-Time Contexts

- Advantages of Stored Procedures

- The JServer JVM and Its Components

- Developing Stored Procedures: An Overview

## Java and the RDBMS: A Robust Combination

The Oracle RDBMS provides Java applications with a dynamic data-processing engine that supports complex queries and different views of the same data. All client requests are assembled as data queries for immediate processing, and query results are generated on the fly.

Several features make Java ideal for server programming. Java lets you assemble applications using off-the-shelf software components (JavaBeans). Its type safety and automatic memory management allow for tight integration with the RDBMS. In addition, Java supports the transparent distribution of application components across a network.

Thus, Java and the RDBMS support the rapid assembly of component-based, network-centric applications that can evolve gracefully as business needs change. In addition, you can move applications and data stores off the desktop and onto intelligent networks and network-centric servers. More important, you can access those applications and data stores from any client device.

Figure 1-1 shows a traditional two-tier, client/server configuration in which clients call Java stored procedures the same way they call PL/SQL stored procedures. (PL/SQL is an advanced 4GL tightly integrated with Oracle8i.) The figure also shows how the Net8 Connection Manager can funnel many network connections into a single database connection. This enables the RDBMS to support a large number of concurrent users.

#### Figure 1-1 Two-Tier Client/Server Configuration

## Stored Procedures and Run-Time Contexts

Stored procedures are Java methods published to SQL and stored in an Oracle database for general use. To publish Java methods, you write call specifications (call specs for short), which map Java method names, parameter types, and return types to their SQL counterparts.

Unlike a wrapper, which adds another layer of execution, a call spec simply publishes the existence of a Java method. So, when you call the method (through its call spec), the run-time system dispatches the call with minimal overhead.

When called by client applications, a stored procedure can accept arguments, reference Java classes, and return Java result values. Figure 1-2 shows a stored procedure being called by various applications.

#### Figure 1-2 Calling a Stored Procedure

Except for graphical-user-interface (GUI) methods, JServer can run any Java method as a stored procedure. The run-time contexts are:

- functions and procedures

- database triggers

- object-relational methods

The next three sections describe these contexts.

### Functions and Procedures

Functions and procedures are named blocks that encapsulate a sequence of statements. They are like building blocks that you can use to construct modular, maintainable applications.

Generally, you use a procedure to perform an action, and a function to compute a value. So, for `void` Java methods, you use procedure call specs, and for value-returning methods, you use function call specs.

Only top-level and packaged (not local) PL/SQL functions and procedures can be used as call specs. When you define them using the SQL `CREATE` `FUNCTION`, `CREATE` `PROCEDURE`, and/or `CREATE` `PACKAGE` statement, they are stored in the database, where they are available for general use.

Java methods published as functions and procedures must be invoked explicitly. They can accept arguments and are callable from:

- SQL DML statements (`INSERT`, `UPDATE`, `DELETE`, and `SELECT`)

- SQL `CALL` statements

- PL/SQL blocks, subprograms, and packages

### Database Triggers

A database trigger is a stored procedure associated with a specific table or view. Oracle invokes (fires) the trigger automatically whenever a given DML operation modifies the table or view.

A trigger has three parts: a triggering event (DML operation), an optional trigger constraint, and a trigger action. When the event occurs, the trigger fires and a `CALL` statement calls a Java method (through its call spec) to perform the action.

Database triggers, which you define using the SQL `CREATE` `TRIGGER` statement, let you customize the RDBMS. For example, they can restrict DML operations to regular business hours. Typically, triggers are used to enforce complex business rules, derive column values automatically, prevent invalid transactions, log events transparently, audit transactions, or gather statistics.

### Object-Relational Methods

A SQL object type is a user-defined composite datatype that encapsulates a set of variables (attributes) with a set of operations (methods), which can be written in Java. The data structure formed by the set of attributes is public (visible to client programs). However, well-behaved programs do not manipulate it directly. Instead, they use the set of methods provided.

When you define an object type using the SQL `CREATE` ... `OBJECT` statement, you create an abstract template for some real-world object. The template specifies only those attributes and behaviors the object will need in the application environment. At run time, when you fill the data structure with values, you create an instance of the object type. You can create as many instances (objects) as necessary.

Typically, an object type corresponds to some business entity such as a purchase order. To accommodate a variable number of items, object types can use variable-length arrays (varrays) and nested tables. For example, this feature enables a purchase order object type to contain a variable number of line items.

## Advantages of Stored Procedures

Stored procedures offer several advantages including better performance, higher productivity, ease of use, and increased scalability.

### Performance

Stored procedures are compiled once and stored in executable form, so procedure calls are quick and efficient. Executable code is automatically cached and shared among users. This lowers memory requirements and invocation overhead.

By grouping SQL statements, a stored procedure allows them to be executed with a single call. This minimizes the use of slow networks, reduces network traffic, and improves round-trip response time. OLTP applications, in particular, benefit because result-set processing eliminates network bottlenecks.

Additionally, stored procedures enable you to take advantage of the computing resources of the server. For example, you can move computation-bound procedures from client to server, where they will execute faster. Likewise, stored functions called from SQL statements enhance performance by executing application logic within the server.

### Productivity and Ease of Use

By designing applications around a common set of stored procedures, you can avoid redundant coding and increase your productivity. Moreover, stored procedures let you extend the functionality of the RDBMS. For example, stored functions called from SQL statements enhance the power of SQL.

You can use the Java integrated development environment (IDE) of your choice to create stored procedures. Then, you can deploy them on any tier of the network architecture. Moreover, they can be called by standard Java interfaces such as JDBC, CORBA, and EJB and by programmatic interfaces and development tools such as SQLJ, the OCI, Pro*C/C++, and JDeveloper.

This broad access to stored procedures lets you share business logic across applications. For example, a stored procedure that implements a business rule can be called from various client-side applications, all of which can share that business rule. In addition, you can leverage the server's Java facilities while continuing to write applications for your favorite programmatic interface.

### Scalability

Stored procedures increase scalability by isolating application processing on the server. In addition, automatic dependency tracking for stored procedures aids the development of scalable applications.

The shared memory facilities of the Multi-Threaded Server (MTS) enable Oracle8i to support more than 10,000 concurrent users on a single node. For more scalability, you can use the Net8 Connection Manager to multiplex Net8 connections.

### Maintainability

Once it is validated, you can use a stored procedure with confidence in any number of applications. If its definition changes, only the procedure is affected, not the applications that call it. This simplifies maintenance and enhancement. Also, maintaining a procedure on the server is easier than maintaining copies on different client machines.

### Interoperability

Within the RDBMS, Java conforms fully to the Java Language Specification and furnishes all the advantages of a general-purpose, object-oriented programming language. Also, as with PL/SQL, Java provides full access to Oracle data, so any procedure written in PL/SQL can be written in Java.

PL/SQL stored procedures complement Java stored procedures. Typically, SQL programmers who want procedural extensions favor PL/SQL, and Java programmers who want easy access to Oracle data favor Java.

The RDBMS allows a high degree of interoperability between Java and PL/SQL. Java applications can call PL/SQL stored procedures using an embedded JDBC driver; conversely, PL/SQL applications can call Java stored procedures directly.

### Replication

With Oracle Advanced Replication, you can replicate (copy) stored procedures from one Oracle8i database to another. That feature makes them ideal for implementing a central set of business rules. Once you write them, you can replicate and distribute the stored procedures to work groups and branch offices throughout the company. In this way, you can revise policies on a central server rather than on individual servers.

### Security

The Oracle JServer uses Java 2 security to protect its Java virtual machine. All classes are loaded into a secure database, so they are "untrusted". To access classes and operating system resources, a user needs the proper permissions. Likewise, all stored procedures are secured against other users (to whom you can grant the database privilege `EXECUTE`).

You can restrict access to Oracle data by allowing users to manipulate the data only through stored procedures that execute with their definer's privileges. For example, you can allow access to a procedure that updates a database table, but deny access to the table itself.

For a full discussion of JServer security, see the Oracle8i Java Developer's Guide.

## The JServer JVM and Its Components

The JServer Java virtual machine (JVM) is a complete, Java 2-compliant Java execution environment. It runs in the same process space and address space as the RDBMS kernel, sharing its memory heaps and directly accessing its relational data. This design optimizes memory use and increases throughput.

The JServer JVM provides a run-time environment for Java objects. It fully supports Java data structures, method dispatch, exception handling, and language-level threads. It also supports all the core Java class libraries including `java.lang`, `java.io`, `java.net`, `java.math`, and `java.util`. Figure 1-3 shows its main components.

#### Figure 1-3 Main Components of the JServer JVM

The JServer JVM embeds the standard Java namespace in RDBMS schemas. This feature lets Java programs access Java objects stored in Oracle databases and application servers across the enterprise.

In addition, the JVM is tightly integrated with the scalable, shared memory architecture of the RDBMS. Java programs use call, session, and object lifetimes efficiently without your intervention. So, you can scale JServer and middle-tier Java business objects, even when they have session-long state.

### The JServer JVM versus Client JVMs

This section discusses some important differences between the JServer JVM and typical client JVMs.

#### Method main()

Client-based Java applications declare a single, top-level method (`main()`) that defines the profile of an application. As with applets, server-based applications have no such "inner loop". Instead, they are driven by logically independent clients.

Each client begins a session, calls its server-side logic modules through top-level entry points, and eventually ends the session. The server environment hides the managing of sessions, networks, and other shared resources from hosted Java programs.

#### The GUI

A server cannot provide GUIs, but it can supply the logic that drives them. For example, the JServer JVM does not supply the basic GUI components found in the JDK's Abstract Windowing Toolkit (AWT). However, all AWT Java classes are available within the server environment. So, your programs can use AWT functionality, as long as they do not attempt to materialize a GUI on the server.

#### The IDE

The JServer JVM is oriented to Java application deployment, not development. You can write and unit-test applications in your favorite IDE, then deploy them for execution within the RDBMS.

Java's binary compatibility allows you to work in any IDE, then upload Java class files to the server. You need not move your Java source files to the database. Instead, you can use powerful client-side IDEs to maintain Java applications that are deployed on the server.

#### Multi-threading

Multi-threaded Java programs execute on the Oracle8i database server without modification. However, in a server environment, Java threads do not increase concurrency (and therefore throughput). Throughput is affected only by MTS mode, the number of OS processes used by the RDBMS, and various tuning methods.

Before porting a multi-threaded application to the server, make sure you understand how threads work with the JServer JVM. The important differences are that on the server:

- Threads run sequentially, not concurrently.

- Threads within a call die when the call ends.

- Threads are cooperative, not preemptive, so if one thread enters an infinite loop, no other threads can run.

Oracle8i multi-threading refers to concurrent user sessions, not Java multi-threading. On the server, throughput is increased by supporting many concurrent user sessions. The scheduling of Java execution (of each call within a session, for example) to maximize throughput is done by the RDBMS, not by Java.

### Main Components of the JServer JVM

This section briefly describes the main components of the JServer JVM and some of the facilities they provide.

#### Library Manager

To store Java classes in an Oracle database, you use the command-line utility `loadjava`, which employs SQL `CREATE` `JAVA` statements to do its work. When invoked by the `CREATE` `JAVA` `{SOURCE` `|` `CLASS` `|` `RESOURCE}` statement, the library manager loads Java source, class, or resource files into the database. You never access these Java schema objects directly; only the JServer JVM uses them.

#### Memory Manager

Automated storage management is one of Java's key features. In particular, the Java run-time system requires automatic garbage collection (deallocation of memory held by unused objects). The memory manager uses memory allocation techniques tuned to object lifetimes. Objects that survive beyond call boundaries are migrated to appropriate memory areas. Also, the memory manager minimizes the footprint per session by sharing immutable object state such as class definitions and final static variables.

#### Compiler

The JServer JVM includes a standard Java 2 (also known as JDK 1.2) Java compiler. When invoked by the `CREATE` `JAVA` `SOURCE` statement, it translates Java source files into architecture-neutral, one-byte instructions known as bytecodes. Each bytecode consists of an opcode followed by its operands. The resulting Java class files, which conform fully to the Java standard, are submitted to the interpreter at run time.

#### Interpreter

To execute Java programs, the JServer JVM includes a standard Java 2 bytecode interpreter. The interpreter and associated Java run-time system execute standard Java class files. For high throughput, the interpreter runs on the Multi-Threaded Server, which manages sessions and schedules the execution of Java programs. The run-time system supports native methods and call-in/call-out from the host environment.

Note: Although your own code is interpreted, the JServer JVM uses natively compiled versions of the core Java class libraries, object request broker (ORB), SQLJ translator, and JDBC drivers. For more information, see "JServer Accelerator".

#### Class Loader

In response to requests from the run-time system, the Java class loader locates, loads, and initializes Java classes stored in the database. The class loader reads the class, then generates the data structures needed to execute it. Immutable data and metadata are loaded into initialize-once shared memory. As a result, less memory is required per session. The class loader attempts to resolve external references when necessary. Also, it invokes the Java compiler automatically when Java class files must be recompiled (and the source files are available).

#### Verifier

Java class files are fully portable and conform to a well-defined format. The verifier prevents the inadvertent use of "spoofed" Java class files, which might alter program flow or violate access restrictions. Oracle security and Java security work with the verifier to protect your applications and data.

#### Server-Side JDBC Internal Driver

JDBC is a standard set of Java classes providing vendor-independent access to relational data. Specified by Sun Microsystems and modeled after ODBC (Open Database Connectivity) and the X/Open SQL CLI (Call Level Interface), the JDBC classes supply standard features such as simultaneous connections to several databases, transaction management, simple queries, calls to stored procedures, and streaming access to `LONG` column data.

Using low-level entry points, a specially tuned JDBC driver runs directly inside the RDBMS, thereby providing the fastest access to Oracle data from Java stored procedures. The server-side internal JDBC driver complies fully with the Sun Microsystems JDBC specification. Tightly integrated with the RDBMS, it supports Oracle-specific datatypes, NLS character sets, and stored procedures. Additionally, the client-side and server-side JDBC APIs are the same, which makes it easy to partition applications.

#### Server-Side SQLJ Translator

SQLJ enables you to embed SQL statements in Java programs. It is more concise than JDBC and more amenable to static analysis and type checking. The SQLJ preprocessor, itself a Java program, takes as input a Java source file in which SQLJ clauses are embedded. Then, it translates the SQLJ clauses into Java class definitions that implement the specified SQL statements. The Java type system ensures that objects of those classes are called with the correct arguments.

A highly optimized SQLJ translator runs directly inside the RDBMS, where it provides run-time access to Oracle data using the server-side internal JDBC driver. SQLJ forms can include queries, DML, DDL, transaction control statements, and calls to stored procedures. The client-side and server-side SQLJ APIs are identical, which makes it easy to partition applications.

#### JServer Accelerator

The JServer Accelerator is a native-code compiler that speeds up the execution of Java programs by eliminating interpreter overhead. It translates standard Java class files into specialized C source files that are processed by a platform-dependent C compiler into shared libraries, which the JServer JVM can load dynamically.

Unlike just-in-time (JIT) compilers, which rely on processor-specific code, the JServer Accelerator is portable to all OS and hardware platforms. To speed up your applications, the JServer JVM has natively compiled versions of the core Java class libraries, ORB, SQLJ translator, and JDBC drivers.

Although the Java programs you load into the database are interpreted, they use natively compiled facilities. In addition, the core JDK classes and supplied Oracle classes that the programs use are natively compiled. As Figure 1-4 shows, natively compiled code executes up to ten times faster than interpreted code. So, the more native code your program uses, the faster it executes.

#### Figure 1-4 Interpreter versus JServer Accelerator

## Developing Stored Procedures: An Overview

To develop Java stored procedures, take the five steps outlined below. This section shows you how to develop a simple Java stored procedure. For a detailed example showing the design and implementation of a Java stored procedures application, see Chapter 5.

### Step 1: Create or Reuse the Java Classes

Use your favorite Java IDE to create classes, or simply reuse existing classes that meet your needs. Oracle's Java facilities support many Java development tools and client-side programmatic interfaces. For example, the JServer JVM accepts programs developed in popular Java IDEs such as Symantec's Visual Café, Oracle's JDeveloper, and Borland's JBuilder.

In the example below, you create the public class `Oscar`. It has a single method named `quote()`, which returns a quotation from Oscar Wilde.

    public class Oscar {
      // return a quotation from Oscar Wilde
      public static String quote() {
        return "I can resist everything except temptation.";
      }
    }

In the following example, using Sun Microsystems's JDK Java compiler, you compile class `Oscar` on your client workstation:

    javac Oscar.java

The compiler outputs a Java binary file--in this case, `Oscar.class`.

### Step 2: Load and Resolve the Java Classes

Using the utility `loadjava`, you can upload Java source, class, and resource files into an Oracle database, where they are stored as Java schema objects. You can run `loadjava` from the command line or from an application, and you can specify several options including a resolver.

In the example below, `loadjava` connects to the database using the default JDBC OCI driver. You must specify the username and password. By default, class `Oscar` is loaded into the logon schema (in this case, `scott`).

    > loadjava -user scott/tiger Oscar.class

Later, when you call method `quote()`, the server uses a resolver (in this case, the default resolver) to search for supporting classes such as `String`. The default resolver searches first in the current schema, then in schema `SYS`, where all the core Java class libraries reside. If necessary, you can specify different resolvers.

For more information, see Chapter 2.

### Step 3: Publish the Java Classes

For each Java method callable from SQL, you must write a call spec, which exposes the method's top-level entry point to Oracle. Typically, only a few call specs are needed, but if you like, Oracle's JDeveloper can generate them for you.

In the following example, from SQL*Plus, you connect to the database, then define a top-level call spec for method `quote()`:

    SQL> connect scott/tiger

    SQL> CREATE FUNCTION oscar_quote RETURN VARCHAR2
      2  AS LANGUAGE JAVA
      3  NAME 'Oscar.quote() return java.lang.String';

For more information, see Chapter 3.

### Step 4: Call the Stored Procedures

You can call Java stored procedures from SQL DML statements, PL/SQL blocks, and PL/SQL subprograms. Using the SQL `CALL` statement, you can also call them from the top level (from SQL*Plus, for example) and from database triggers.

In the following example, you declare a SQL*Plus host variable:

    SQL> VARIABLE theQuote VARCHAR2(50);

Then, you call the function `oscar_quote()`, as follows:

    SQL> CALL oscar_quote() INTO :theQuote;

    SQL> PRINT theQuote;

    THEQUOTE
    --------------------------------------------------
    I can resist everything except temptation.

For more information, see Chapter 4.

### Step 5: If Necessary, Debug the Stored Procedures

Your Java stored procedures execute remotely on a server, which typically resides on a separate machine. However, the JDK debugger (`jdb`) cannot debug remote Java programs, so JServer provides a way to debug them.

The class `DebugProxy` makes remote Java programs appear to be local. It lets any debugger that supports the `sun.tools.debug.Agent` protocol connect to a program as if the program were local. The proxy forwards requests to the server and returns results to the debugger.

For detailed instructions, see the Oracle8i Java Developer's Guide.

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