DBA Tips Archive for Oracle |
Introduction to Java Stored Procedures - (JServer / Oracle 8i)
by Jeff Hunter, Sr. Database Administrator
Contents
Introduction to JServer
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.
The run-time contexts for Java Stored Procedures are:
This article
(much of which is taken from the "Oracle8i Java Stored Procedures Developer's Guide: Part No. A81358-01")
will attempt to introduce the steps required in writting Java Stored Procedures within the Oracle 8i database.
Located at the end of this article is a small example call JServerApplication. It contains a short JDBC program
along with scripts to load/compile and create all necessary "Call Specs".
Installing on Oracle8i
The JServer JVM versus 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:
The JServer JVM and Its Components
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.
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.
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.
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.
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 the figure below 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.
Developing Stored Procedures: An Overview
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 Cafe, 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.
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).
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():
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:
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.
Example JServer Application
Copyright (c) 1998-2013 Jeffrey M. Hunter. All rights reserved.
All articles, scripts and material located at the Internet address of http://www.idevelopment.info is the copyright of Jeffrey M. Hunter
and is protected under copyright laws of the United States. This document may not be hosted on any other site without my express,
prior, written permission. Application to host any of the material elsewhere can be made by contacting me at jhunter@idevelopment.info.
I have made every effort and taken great care in making sure that the material included on my web site is technically accurate,
but I disclaim any and all responsibility for any loss, damage or destruction of data or any other property which may arise from
relying on it. I will in no case be liable for any monetary damages arising from such loss, damage or destruction.
Starting with Version 8i (8.1.5), Oracle now provides the ability to write Java
Stored Procedures within the database. 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.
Installing JServer
First, determine whether Java has previously been loaded into the database,
invoke SQL*Plus (sqlplus), connect as internal and run the following:
SQL> describe dbms_java
If the result is:
ERROR:
ORA-04043: object dbms_java does not exist
then java has not previously been loaded in the database.
If the result is a long package description, then java
is already loaded in the database.
% sqlplus "/ as sysdba"
spool jvminst.log;
@$ORACLE_HOME/javavm/install/initjvm.sql;
spool off
spool initxml.log;
@$ORACLE_HOME/oracore/admin/initxml.sql
spool off
spool catxsu.log;
@$ORACLE_HOME/rdbms/admin/catxsu.sql
spool off
spool init_jis.log;
@$ORACLE_HOME/javavm/install/init_jis.sql
spool off
spool jisja.log;
@$ORACLE_HOME/javavm/install/jisja.sql
spool off
spool jisaephc.log;
@$ORACLE_HOME/javavm/install/jisaephc.sql
spool off
spool initplgs.log;
@$ORACLE_HOME/rdbms/admin/initplgs.sql
spool off
spool initjsp.log;
@$ORACLE_HOME/jsp/install/initjsp.sql
spool off
spool jspja.log;
@$ORACLE_HOME/jsp/install/jspja.sql
spool off
spool initplsj.log;
@$ORACLE_HOME/rdbms/admin/initplsj.sql
spool off
spool initjms.log;
@$ORACLE_HOME/rdbms/admin/initjms.sql
spool off
spool initrepapi.log;
@$ORACLE_HOME/rdbms/admin/initrepapi.sql
spool off
spool initsoxx.log;
@$ORACLE_HOME/rdbms/admin/initsoxx.sql
spool off
exit;
Installing on Oracle9i
% sqlplus "/ as sysdba"
set echo on
spool JServer.log
@$ORACLE_HOME/javavm/install/initjvm.sql;
@$ORACLE_HOME/xdk/admin/initxml.sql;
@$ORACLE_HOME/xdk/admin/xmlja.sql;
@$ORACLE_HOME/javavm/install/init_jis.sql $ORACLE_HOME;
@$ORACLE_HOME/javavm/install/jisaephc.sql $ORACLE_HOME;
@$ORACLE_HOME/javavm/install/jisja.sql $ORACLE_HOME;
@$ORACLE_HOME/javavm/install/jisdr.sql 2481 2482;
@$ORACLE_HOME/jsp/install/initjsp.sql;
@$ORACLE_HOME/jsp/install/jspja.sql;
@$ORACLE_HOME/rdbms/admin/initjms.sql;
@$ORACLE_HOME/rdbms/admin/initrapi.sql;
@$ORACLE_HOME/rdbms/admin/initsoxx.sql;
@$ORACLE_HOME/rdbms/admin/initapcx.sql;
@$ORACLE_HOME/rdbms/admin/initcdc.sql;
@$ORACLE_HOME/rdbms/admin/initqsma.sql;
@$ORACLE_HOME/rdbms/admin/initsjty.sql;
@$ORACLE_HOME/rdbms/admin/initaqhp.sql;
spool off
exit;
This section discusses some important differences between the JServer JVM and
typical client JVMs.
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.
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.


Step 1: Create or Reuse the Java Classes
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.
% 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.
SQL> connect scott/tiger
SQL> CREATE FUNCTION oscar_quote RETURN VARCHAR2
2 AS LANGUAGE JAVA
3 NAME 'Oscar.quote() return java.lang.String';
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.
Example:
JServerApplication.java
JServerApplication.java is a small Java program that attempts to use many of the
more common features in JDBC.
LoadJServerApplication.sh
LoadJServerApplication.sh is a UNIX shell script that can be used to Load/Compile
the JServerApplication.java into the Oracle Database.
CallSpecJServerApplication.sql
CallSpecJServerApplication.sql is used to create the "Call Specs" needed to the
example JServerApplication Application.
RunJServerApplication.sql
The RunJServerApplication.sql can be used to run JServerApplication.
JServerApplicationResults.out
Example output of JServerApplication.
Thursday, 18-Nov-2010 18:17:50 EST
Page Count: 55700