Examining Loaded Java Elements

Once you have loaded Java source, class, and resource elements into the database, information about those elements is available in several different data dictionary views, as shown in Table 22-4.

Table 22-4. Class information in data dictionary views
View Description
USER_OBJECTS ALL_OBJECTS DBA_OBJECTS Contains header information about your objects of JAVA SOURCE, JAVA CLASS, and JAVA RESOURCE types
USER_ERRORS ALL_ERRORS DBA_ERRORS Contains any compilation errors encountered for your objects
USER_SOURCE Contains the source code for your Java source if and only if you used the CREATE JAVA SOURCE command to create the Java schema object

You can write queries against these views, or you can build programs to access the information in a variety of useful ways. For example, here is a query that shows all of the Java-related objects in my schema:

/ *Files on web: showjava.sql and myJava.pkg */COLUMN object_name FORMAT A30SELECT object_name, object_type, status, timestamp FROM user_objects WHERE (object_name NOT LIKE 'SYS_%' AND object_name NOT LIKE 'CREATE$%' AND object_name NOT LIKE 'JAVA$%' AND object_name NOT LIKE 'LOADLOB%') AND object_type LIKE 'JAVA %' ORDER BY object_type, object_name;

The WHERE clause filters out those objects created by Oracle for managing Java objects. Here is some sample output:

SQL> exec myJava.showObjectsOBJECT_NAME OBJECT_TYPE STATUS TIMESTAMP--------------------- ------------ ------- -------------------Hello JAVA CLASS VALID 1999-05-19:16:42:27JFile2 JAVA CLASS VALID 1999-05-26:17:07:11JFile3 JAVA CLASS VALID 1999-05-27:12:53:46plsolutions/java/putLn JAVA SOURCE VALID 1999-05-19:16:30:29

The myjava.pkg file on the O'Reilly site contains a packaged version of this query, allowing you to view your Java objects with this procedure call:

SQL> exec myJava.showobjects

The following lets you see a list of all the Java elements whose names start with OE:

SQL> exec myJava.showobjects ('OE%')

The USER_OBJECTS view's object_name column contains the full names of Java schema objects, unless the name is longer than 30 characters or contains an untranslatable character from the Unicode character set. In both cases, the short name is displayed in the object_name column. To convert short names to full names, you can use the LONGNAME function in the utility package DBMS_JAVA, which is explored in the next section.

22.7 Using DBMS_ JAVA

The Oracle built-in package DBMS_JAVA gives you access to and the ability to modify various characteristics of the Aurora Java Virtual Machine.

The DBMS_JAVA package contains a large number of programs, many of which are intended for Oracle internal use only. Nevertheless, we can take advantage of a number of very useful programs; most can also be called within SQL statements. Table 22-5 summarizes some of the DBMS_JAVA programs. As noted earlier in the chapter, DBMS_JAVA also offers programs to manage security and permissions.

Table 22-5. Common DBMS_JAVA programs
Program Description
LONGNAME function Obtains the full (long) Java name for a given Oracle short name
GET_COMPILER_OPTION function Looks up an option in the Java options table
SET_COMPILER_OPTION procedure Sets a value in the Java options table and creates the table, if one does not exist
RESET_COMPILER_OPTION procedure Resets a compiler option in the Java options table
SET_OUTPUT procedure Redirects Java output to the DBMS_OUTPUT text buffer
EXPORT_SOURCE procedure Exports a Java source schema object into an Oracle large object (LOB)
EXPORT_RESOURCE procedure Exports a Java resource schema object into an Oracle large object
EXPORT_CLASS procedure Exports a Java class schema object into an Oracle large object

These programs are explored in detail in the following sections.

22.7.1 LONGNAME: Converting Java Long Names

Java class andmethod names can easily exceed the maximum SQL identifier length of 30 characters. In such cases, Oracle creates a unique "short name" for the Java code element and uses that name for SQL- and PL/SQL-related access.

Use the following function to obtain the full (long) name for a given short name:

FUNCTION DBMS_JAVA.LONGNAME (shortname VARCHAR2) RETURN VARCHAR2

The following query displays the long names for all Java classes defined in the currently connected schema for which the long names and short names do not match:

/* File on web: longname.sql */SELECT object_name shortname, DBMS_JAVA.LONGNAME (object_name) longname FROM USER_OBJECTS WHERE object_type = 'JAVA CLASS' AND object_name != DBMS_JAVA.LONGNAME (object_name);

This query is also available inside the myJava package (found in the myJava.pkg file); its use is shown here. Suppose that I define a class with this name:

public class DropAnyObjectIdentifiedByTypeAndName {

That is too long for Oracle, and we can verify that Oracle creates its own short name as follows:

SQL> exec myJava.showlongnamesShort Name | Long Name----------------------------------------------------Short: /247421b0_DropAnyObjectIdentifLong: DropAnyObjectIdentifiedByTypeAndName

22.7.2 GET_, SET_, and RESET_COMPILER_OPTION: Getting and Setting Compiler Options

You can also set compiler option values in the database table JAVA$OPTIONS (called the 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 to set the options differently for different source schema objects.

The compiler looks up options in the options table unless they are specified on the loadjava command line. If there is no options-table entry or command-line value for an option, the compiler uses the following default values (you can find more information about nondefault values in Oracle's SQLJDeveloper'sGuideandReference documentation):

encoding = latin1online = true // applies only to SQLJ source files

You can get and set options-table entries using the following DBMS_ JAVA functions and procedures:

FUNCTION DBMS_JAVA.GET_COMPILER_OPTION ( what VARCHAR2, optionName VARCHAR2) PROCEDURE DBMS_JAVA.SET_COMPILER_OPTION ( what VARCHAR2, optionName VARCHAR2, value VARCHAR2) PROCEDURE DBMS_JAVA.RESET_COMPILER_OPTION ( what VARCHAR2, optionName VARCHAR2)

The parameter what 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 what most closely matches the full name of the schema object. If what is the empty string, it matches the name of any schema object.

optionName is the name of the option being set. 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');

22.7.3 SET_OUTPUT: Enabling Output from Java

The System.out and System.err classes send their output to the current trace files (when executed within the Oracle database). This is not a very convenient repository if you simply want to test your code to see if it is working properly. DBMS_JAVA supplies a procedure you can call to redirect output to the DBMS_OUTPUT text buffer so that it can be flushed to your SQL*Plus screen automatically. The syntax of this procedure is:

PROCEDURE DBMS_JAVA.SET_OUTPUT (buffersize NUMBER);

Here is an example of how you would use this program:

//* File on web: ssoo.sql */SET SERVEROUTPUT ON SIZE 1000000CALL DBMS_JAVA.SET_OUTPUT (1000000);

Documentation on the interaction between these two commands is skimpy; my testing has uncovered the following rules:

· The minimum (and default) buffer size is a measly 2000 bytes; the maximum size is 1,000,000 bytes. You can pass a number outside of that range without causing an error; unless the number is really big, it will simply be ignored.

· The buffer size specified by SET SERVEROUTPUT supersedes that of DBMS_JAVA.SET_OUTPUT. In other words, if you provide a smaller value for the DBMS_JAVA call, it will be ignored, and the larger size will be used.

· If your output in Java exceeds the buffer size, you will not receive the error you get with DBMS_OUTPUT, namely:

ORA-10027: buffer overflow, limit of nnn bytes

The output will instead be truncated to the buffer size specified, and execution of your code will continue.

As is the case with DBMS_OUTPUT, you will not see any output from your Java calls until the stored procedure through which they are called finishes executing.

22.7.4 EXPORT_SOURCE, EXPORT_RESOURCE, and EXPORT_CLASS: Exporting Schema Objects

Oracle's DBMS_JAVA package offers the following set of procedures to export source, resources, and classes:

PROCEDURE DBMS_JAVA.EXPORT_SOURCE ( name VARCHAR2, [ blob BLOB | clob CLOB ] ); PROCEDURE DBMS_JAVA.EXPORT_SOURCE ( name VARCHAR2, schema VARCHAR2, [ blob BLOB | clob CLOB ] ); PROCEDURE DBMS_JAVA.EXPORT_RESOURCE ( name VARCHAR2, [ blob BLOB | clob CLOB ] ); PROCEDURE DBMS_JAVA.EXPORT_RESOURCE ( name VARCHAR2, schema VARCHAR2, [ blob BLOB | clob CLOB ] ); PROCEDURE DBMS_JAVA.EXPORT_CLASS ( name VARCHAR2, blob BLOB ); PROCEDURE DBMS_JAVA.EXPORT_CLASS ( name VARCHAR2, schema VARCHAR2, blob BLOB );

In all cases, name is the name of the Java schema object to be exported, schema is the name of the schema owning the object (if not supplied, then the current schema is used), and blob | clob is the large object that receives the specified Java schema object.

You cannot export a class into a CLOB, only into a BLOB. In addition, the internal representation of the source uses the UTF8 format, so that format is used to store the source in the BLOB as well.

The following prototype procedure offers an idea of how you might use the export programs to obtain source code of your Java schema objects, when appropriate:

/* File on web: showjava.sp */CREATE OR REPLACE PROCEDURE show_java_source ( NAME IN VARCHAR2, SCHEMA IN VARCHAR2 := NULL)-- Overview: Shows Java source (prototype). Author: Vadim LoevskiIS b CLOB; v VARCHAR2 (2000); i INTEGER; object_not_available EXCEPTION; PRAGMA EXCEPTION_INIT (object_not_available, -29532); BEGIN /* Move the Java source code to a CLOB. */ DBMS_LOB.createtemporary (b, FALSE ); dbms_java.export_source (name, NVL (SCHEMA, USER), b); /* Read the CLOB to a VARCHAR2 variable and display it. */ i := 1000; DBMS_LOB.READ (b, i, 1, v); DBMS_OUTPUT.PUT_LINE (v); EXCEPTION -- If the named object does not exist, an exception is raised. WHEN object_not_available THEN IF (SQLERRM) LIKE '%no such%object' THEN DBMS_OUTPUT.put_line ('Java object cannot be found.' ); END IF;END;/

If I then create a Java source object using the CREATE JAVA statement as follows:

CREATE OR REPLACE JAVA SOURCE NAMED "Hello" AS public class Hello { public static String hello( ) { return "Hello Oracle World";} };/

I can view the source code as shown here (assuming that DBMS_OUTPUT has been enabled):

SQL> exec show_java_source ('Hello')public class Hello { public static String hello( ) { return "Hello Oracle World"; } };

22.8 Publishing and Using Java in PL/SQL

Once you have written your Java classes and loaded them into the Oracle RDBMS, you can call their methods from within PL/SQL (and SQL)—but only after you "publish" those methods via a PL/SQL wrapper.