Oracle® Database JPublisher User's Guide 10g Release 1 (10.1) Part Number B10983-01 |
|
|
View PDF |
This chapter provides an introduction and overview of the JPublisher utility, concluding with a summary of JPublisher operations and a sample translation. It covers the following topics:
JPublisher is a utility, written entirely in Java, that generates Java classes to represent database entities such as SQL objects and PL/SQL packages in your Java client program. It also provides support for publishing from SQL, PL/SQL, or server-side Java to Web services and for enabling invocation of external Web services from inside the database.
JPublisher can create classes to represent the following types of database entities:
User-defined SQL object types
Object reference types (REF types)
User-defined SQL collection types (VARRAY types or nested table types)
PL/SQL packages
Server-side Java classes
SQL queries and DML statements
JPublisher enables you to specify and customize the mapping of these entities to Java classes in a strongly typed paradigm.
The utility generates get
XXX
()
and set
XXX
()
accessor methods for each attribute of an object type. If your object types have stored procedures, then JPublisher can generate wrapper methods to invoke the stored procedures. In this scenario, a wrapper method is a Java method that invokes a stored procedure that executes in Oracle Database.
JPublisher can also generate classes for PL/SQL packages. These classes have wrapper methods to invoke the stored procedures in a PL/SQL package.
Instead of using JPublisher-generated classes directly, you can:
Extend the generated classes. This process is straightforward, because JPublisher can also generate initial versions of the subclasses for you, to which you can add your desired functionality.
Write your own Java classes by hand, without using JPublisher. This approach is flexible, but time-consuming and error-prone.
Use generic, weakly typed classes of the oracle.sql
package to represent object, object reference, and collection types. If these classes meet your requirements, then you do not need JPublisher. Typically, you would use this approach if you must be able to generically process any SQL object, collection, reference, or OPAQUE type.
In addition, JPublisher simplifies access to PL/SQL types from Java. You can employ predefined or user-defined mappings between PL/SQL and SQL types, as well as make use of PL/SQL conversion functions between such types. With these mappings in place, JPublisher can automatically generate all the required Java and PL/SQL code.
Paralleling the functionality of publishing SQL or PL/SQL entities to Java, it is also possible to publish server-side Java to client-side Java, effectively allowing your application to make direct calls to Java classes in the database.
Several features enable exposure of generated Java classes—from publishing either SQL or PL/SQL entities or server-side Java entities—as Web services. See "Summary of JPublisher Support for Web Services" for an overview of these features.
The following sections provide an overview of JPublisher new features and requirements, and how JPublisher uses SQLJ in its code generation:
Key new JPublisher features in Oracle Database 10g can be categorized as follows:
JPublisher is used in publishing from SQL or PL/SQL to Java, or in publishing from server-side Java to client-side Java, with new features in place to enable exposure of generated Java classes as Web services for invocation from outside the database. There are two stages to this:
Publishing from SQL or PL/SQL to Java (by JPublisher)
Publishing from Java to Web services (by the Oracle Web services assembler tool)
There are also new features to load and wrap client proxy classes so that external Web services can be invoked from Java or PL/SQL inside the database.
New JPublisher features in Oracle Database 10g include the following. For a more detailed overview, including how these features relate to Web services, see "Summary of JPublisher Support for Web Services".
Generation of Java interfaces
Style files for Java-to-Java type mappings
REF CURSOR returning and result set mapping
Additional support for filtering what JPublisher publishes
Support for publishing server-side Java classes
Support for publishing SQL queries or SQL DML statements
Support for Web services call-outs from the database
Also see "Publishing Server-Side Java Classes" and "Publishing SQL Queries or DML Statements".
Prior to Oracle Database 10g, UNIX releases of JPublisher ignored the environment classpath, instead using a classpath provided through the JPublisher command line that included the required JPublisher and JDBC classes. In Oracle Database 10g, the environment classpath is appended to the classpath that is provided through the command line.
On all platforms now, JPublisher picks up the environment classpath. This feature ensures successful execution in circumstances in which JPublisher must be able to load user-provided types, such as for Web services call-outs and the conversion of Java types during publishing. The term Web services call-outs refers to calling Web services from inside the database by loading the Web services client proxies into the database and generating Java and PL/SQL wrappers for these client proxies. For more information, see "Options to Facilitate Web Services Call-Outs" and "Code Generation for Wrapper Class and PL/SQL Wrapper Options". (By contrast, the term Web services call-ins refers to the functionality of having SQL, PL/SQL, and server-side Java classes in Oracle Database that are accessible to Web services clients.)
Awareness of the environment classpath also plays a role in how JPublisher can represent query results. See "Mapping of REF CURSOR Types and Result Sets".
In most cases, such as whenever wrapper methods are required, JPublisher generates code that uses the Oracle SQLJ implementation. But in Oracle Database 10g, the use of SQLJ is now transparent to the user by default. The next section, "JPublisher Usage of the Oracle SQLJ Implementation", describes this.
The following sections describe when and how JPublisher uses SQLJ, provide an overview of SQLJ, and discuss backward-compatibility modes that relate to the generation of SQLJ source files:
Note: The Oracle SQLJ translator and runtime libraries are supplied with the JPublisher product. |
The JPublisher utility uses the Oracle SQLJ ("SQL in Java") implementation, generating SQLJ code as an intermediate step in most circumstances—whenever wrapper methods are created, either for classes representing PL/SQL packages or for classes representing SQL object types that define methods (PL/SQL stored procedures). In these circumstances, JPublisher uses the Oracle SQLJ translator during compilation, and the Oracle SQLJ runtime during program execution.
In Oracle Database 10g, as a convenience, JPublisher usage of SQLJ is transparent by default. SQLJ source files that JPublisher generates are automatically translated and deleted unless you specify JPublisher settings to choose otherwise. This automatic translation saves you the step of explicitly translating the files. The resulting .java
files that use SQLJ functionality, and the associated .class
files produced by compilation, define what are still referred to as SQLJ classes. These classes use the Oracle SQLJ runtime APIs during execution. Generated classes that do not use the SQLJ runtime are referred to as non-SQLJ classes. Non-SQLJ classes are generated when JPublisher creates classes for SQL types that do not have stored procedures, or when JPublisher is specifically set to not generate wrapper methods.
For those familiar with SQLJ command-line options, it is possible in Oracle Database 10g to pass options to the SQLJ translator through the JPublisher -sqlj
option. See "Option to Access SQLJ Functionality".
To support its use of SQLJ, JPublisher includes translator.jar
, which contains the JPublisher and SQLJ translator libraries, and runtime12.jar
, which is the SQLJ runtime library for JDK 1.2 and higher.
A SQLJ program is a Java program containing embedded SQL statements that comply with the ISO standard SQLJ Language Reference syntax. SQLJ source code contains a mixture of standard Java source, SQLJ class declarations, and SQLJ executable statements with embedded SQL operations. The use of SQLJ was chosen because of the simplified code that SQLJ uses for database access, compared to JDBC code. In SQLJ, a SQL statement is embedded in a single #sql
statement, while several JDBC statements may be required for the same operation.
Because JPublisher generates code that uses SQLJ features, this document discusses some SQLJ concepts. This section briefly defines some key concepts, for those not already familiar with SQLJ.
Connection contexts: A SQLJ connection context object is a strongly typed database connection object. You can use each connection context class for a particular set of interrelated SQL entities, meaning that all the connections you define using a particular connection context class will use tables, views, and stored procedures that share names and datatypes in common. In theory, the advantage in tailoring connection context classes to sets of SQL entities is in the degree of online semantics-checking that this permits during SQLJ translation. JPublisher does not use online semantics-checking when it invokes the SQLJ translator, but you can use this feature if you choose to work with .sqlj
files directly.
The connection context class used by default is sqlj.runtime.ref.DefaultContext
. The SQLJ default context is a default connection object and is an instance of this class. The DefaultContext
class or any custom connection context class implements the standard sqlj.runtime.ConnectionContext
interface. You can use the JPublisher -context
option to specify the connection context class that JPublisher will instantiate for database connections. See "SQLJ Connection Context Classes (-context)".
Iterators: A SQLJ iterator is a strongly typed version of a JDBC result set and is associated with the underlying database cursor. SQLJ iterators are used first and foremost to take query results from a SELECT
statement. The strong typing is based on the datatype of each query column.
Execution contexts: A SQLJ execution context is an instance of the standard sqlj.runtime.ExecutionContext
class and provides a context in which SQL operations are executed. An execution context instance is associated either implicitly or explicitly with each SQL operation that is executed through SQLJ code.
In Oracle8i and Oracle9i, JPublisher produced .sqlj
source files as visible output, which you could then translate yourself using the SQLJ command-line interface (the sqlj
script in UNIX or the sqlj.exe
program in Microsoft Windows).
In Oracle Database 10g, JPublisher supports several backward-compatibility settings, through its -compatible
option, that allow you to continue to work with generated .sqlj
files in similar fashion:
To have JPublisher skip the step of translating .sqlj
files, so that you can translate them explicitly, set -compatible=sqlj
. Then, to translate the files, you can either run JPublisher again using only the -sqlj
option (as described in "Option to Access SQLJ Functionality") or you can run the SQLJ translator directly through its own command-line interface.
To have JPublisher use "Oracle9i compatibility mode", set -compatible=9i
. This setting results in JPublisher generating .sqlj
files with the same code as in Oracle9i versions. Then you can work directly with the .sqlj
files.
To have JPublisher use "Oracle8i compatibility mode", set -compatible=both8i
or -compatible=8i
. This setting results in JPublisher generating .sqlj
files with the same code as in Oracle8i versions. As with Oracle9i compatibility mode, this mode enables you to work directly with .sqlj
files.
Oracle8i and Oracle9i compatibility modes, particularly the former, result in significant differences in the code that JPublisher generates. If your only goal is to work directly with .sqlj
files, then use the sqlj
setting. For more information, see "Backward Compatibility and Migration" and "Backward Compatibility Option".
This section describes the base requirements for JPublisher, then discusses situations with less stringent requirements.
When you use the JPublisher utility, you must also have classes for the Oracle SQLJ implementation, the Oracle JDBC implementation, and a Sun Microsystems Java Developer's Kit (JDK), among other things.
To use all features of JPublisher, you must generally have the following installed and in your classpath, as applicable:
Oracle Database 10g or Oracle9i database
JPublisher invocation script or executable
The jpub
script (for UNIX) or jpub.exe
program (for Microsoft Windows) must be in your file path. They are typically in ORACLE_HOME
/bin
(or ORACLE_HOME
/sqlj/bin
for manual downloads). With proper setup, if you type just "jpub
" in the command line, you will see information about common JPublisher option and input settings.
JPublisher and SQLJ translator classes
These classes are in the library translator.jar
, typically in ORACLE_HOME
/sqlj/lib
.
Notes:
|
SQLJ runtime classes
The SQLJ runtime library is runtime12.jar
, for JDK 1.2 or higher. It is typically located in ORACLE_HOME
/sqlj/lib
.
Oracle Database 10g or Oracle9i JDBC drivers
The Oracle JDBC library—classes12.jar
for JDK 1.2 or higher, or ojdbc14.jar
for JDK 1.4 specifically—is typically in ORACLE_HOME
/jdbc/lib
. See the Oracle Database JDBC Developer's Guide and Reference for more information about the JDBC files.
Each JDBC library also includes the JPublisher runtime classes in the oracle.jpub.runtime
package.
Web services classes
These classes are included in the library utl_dbws.jar
, typically located in ORACLE_HOME
/sqlj/lib
.
Additional PL/SQL packages and JAR files in the database, as needed
There are packages and JAR files that must be in the database if you use JPublisher features for Web services call-ins, Web services call-outs, support for PL/SQL types, or support for invocation of server-side Java classes. Some are preloaded and some must be loaded manually. See the next section, "Required Packages and JAR Files in the Database".
JDK version 1.2 or higher (JDK 1.4 or higher for Web services call-outs or to map SYS.XMLType
for Web services)
Note that you must be able to invoke the Java compiler, javac
, from the command line. For information about how to specify a JDK version and a compiler version other than the default for the JPublisher environment, see "Java Environment Options".
Some or all of the following PL/SQL packages and JAR files must be present in the database, depending on what JPublisher features you use. Subsections that follow discuss how to verify the presence of these packages and files, and how to load them if they are not present.
SQLJUTL
package, to support PL/SQL types
SQLJUTL2
package, to support invocation of server-side Java classes
UTL_DBWS
package, to support Web services call-outs
utl_dbws_jserver.jar
file, to support JAX-RPC or SOAP client proxy classes for Web services call-outs from Oracle Database 10g
See "Options to Facilitate Web Services Call-Outs" for information about related JPublisher features.
JAR files to support SOAP client proxy classes for Web services call-outs from Oracle9i or Oracle8i databases
For Web services call-outs from Oracle9i or Oracle8i, there is not yet a convenience JAR file to parallel utl_dbws_jserver.jar
. You must load several JAR files instead. Also note that JPublisher does not yet support JAX-RPC client proxy classes in Oracle9i or Oracle8i.
sqljutl.jar
file or its contents, to support Web services call-ins
In Oracle Database 10g, support for Web services call-ins is preloaded in the database Java VM, so the sqljutl.jar
file is unnecessary. In Oracle9i or Oracle8i, you must load the file manually.
Note: TheUTL_DBWS package and utl_dbws_jserver.jar file are associated with each other, both supporting the same set of features. This is also true of the SQLJUTL2 package and sqljutl.jar file. The SQLJUTL package and sqljutl.jar file, however, are not directly associated with each other; their naming is coincidental. |
In Oracle Database 10g, the PL/SQL package UTL_DBWS
is automatically installed in the database SYS
schema. To verify the installation, try to describe the package, as follows:
SQL> describe sys.utl_dbws
If the response indicates that the package is not yet installed, then run the following scripts under SYS
:
ORACLE_HOME/sqlj/lib/utl_dbws_decl.sql ORACLE_HOME/sqlj/lib/utl_dbws_body.sql
In Oracle Database 10g, the PL/SQL packages SQLJUTL
and SQLJUTL2
are automatically installed in the database SYS
schema. To verify the installation, try to describe the packages, as follows:
SQL> describe sys.sqljutl SQL> describe sys.sqljutl2
JPublisher output such as the following indicates that the packages are missing:
Warning: Cannot determine what kind of type is <schema>.<type.> You likely need to install SYS.SQLJUTL. The database returns: ORA-06550: line 1, column 7: PLS-00201: identifier 'SYS.SQLJUTL' must be declared
To install the SQLJUTL
and SQLJUTL2
packages, you must install one of the following files into the SYS
schema:
ORACLE_HOME
/sqlj/lib/sqljutl.sql
(for Oracle9i or Oracle Database 10g)
ORACLE_HOME
/sqlj/lib/sqljutl8.sql
(for Oracle8i)
In Oracle Database 10g, the following file must be loaded into the database for Web services call-outs:
ORACLE_HOME
/sqlj/lib/utl_dbws_jserver.jar
It is not preloaded, but you can verify whether it has already been loaded by running the following query in the SYS
schema:
SQL> select status, object_type from all_objects where dbms_java.longname(object_name)='oracle/jpub/runtime/dbws/DbwsProxy$1';
The following result indicates that the file has already been loaded:
STATUS OBJECT_TYPE ------- ------------------- VALID JAVA CLASS VALID SYNONYM
If it has not already been loaded, you can use the loadjava
utility, such as in the following example:
% loadjava -oci8 -u sys/change_on_install -r -v -f -s -grant public utl_dbws_jserver.jar
Note: Before loading this file, verify that the databasejava_pool_size parameter has a setting of at least 96 MB, and that the shared_pool_size parameter has a setting of at least 80 MB. If this is not the case, update the database parameter file (such as init.ora ) to give these two entries appropriate settings, then restart the database.
See the Oracle Database Java Developer's Guide for information about the |
For Web services call-outs from an Oracle9i or Oracle8i database, use SOAP client proxy classes. For this, you must load a number of JAR files into the database, which you can accomplish with the following command (specifying ORACLE_HOME
and J2EE_HOME
as appropriate):
% loadjava -u sys/change_on_install -r -v -s -f -grant public ORACLE_HOME/soap/lib/soap.jar ORACLE_HOME/dms/lib/dms.jar J2EE_HOME/lib/servlet.jar J2EE_HOME/lib/ejb.jar J2EE_HOME/lib/mail.jar
You can obtain these files from an Oracle Application Server installation. (You would presumably run Web services in conjunction with Oracle Application Server Containers for J2EE.)
Note that JAX-RPC client proxy classes are not yet supported in Oracle9i or Oracle8i.
See the Oracle Database Java Developer's Guide for information about the loadjava
utility.
The following file or its contents must be loaded in the database for server-side Java invocation, such as to support Web services call-ins:
ORACLE_HOME
/sqlj/lib/sqljutl.jar
In Oracle Database 10g, its contents are preloaded in the Java VM. In Oracle9i or Oracle8i, you must load the file manually. To see if it has already been loaded, you can run the following query in the SYS
schema:
SQL> select status, object_type from all_objects where dbms_java.longname(object_name)='oracle/jpub/reflect/Client';
The following result indicates that the file has already been loaded:
STATUS OBJECT_TYPE ------- ------------------- VALID JAVA CLASS VALID SYNONYM
If it has not already been loaded, you can use the loadjava
utility, such as in the following example:
% loadjava -oci8 -u sys/change_on_install -r -v -f -s -grant public sqlj/lib/sqljutl.jar
Note: To load this file, as with the file discussed in the previous section, verify thatjava_pool_size has a setting of at least 96 MB and shared_pool_size has a setting of at least 80 MB. |
If you will not be using certain features of JPublisher, your requirements may be less stringent:
If you never generate classes that implement the Oracle-specific oracle.sql.ORAData
interface (or the deprecated oracle.sql.CustomDatum
interface), you can use a non-Oracle JDBC driver and connect to a non-Oracle database. JPublisher itself, however, must be able to connect to an Oracle database. Be aware that Oracle does not test or support configurations that use non-Oracle components. (See "Representing User-Defined SQL Types Through JPublisher" for an overview of ORAData
.)
If you instruct JPublisher to not generate wrapper methods (through the setting -methods=false
), or if your object types define no methods, then JPublisher will not generate wrapper methods or produce any SQLJ classes. Under these circumstances, there will be no SQLJ translation step, so the SQLJ translator is not required. See "Generation of Package Classes and Wrapper Methods (-methods)" for information about the -methods
option.
If you use JPublisher to generate custom object classes that implement only the deprecated CustomDatum
interface, then you can use the Oracle8i Release 8.1.5 database with the 8.1.5 version of the JDBC driver and with JDK version 1.1 or higher. But it is advisable to upgrade to the ORAData
interface, which requires an Oracle9i or higher JDBC implementation.
If you do not use JPublisher functionality for invocation of server-side Java classes, then you do not need the sqljutl.jar
file to be loaded in the database.
If you do not use JPublisher functionality to enable Web services call-outs, then you do not need utl_dbws.jar
or utl_dbws_jserver.jar
to be loaded in the database.
Be aware of the following when you use JPublisher:
There are limitations to the support for PL/SQL RECORD and indexed-by table types. First, an intermediate wrapper layer is used to map a RECORD or indexed-by-table argument to a SQL type that JDBC supports. In addition, JPublisher cannot fully support the semantics of indexed-by tables. An indexed-by table is similar in structure to a Java Hashtable, but information is lost when JPublisher maps this to a SQL TABLE type (SQL collection). See "Type Mapping Support for PL/SQL RECORD and Indexed-by Table Types" for details about how these types are supported.
If you use an INPUT
file to specify type mappings, note that some potentially disruptive error conditions do not result in error or warning messages from JPublisher. Additionally, there are reserved terms that you are not permitted to use as SQL or Java identifiers. See "INPUT File Precautions" for details.
There is a JPublisher option, -omit_schema_names
, that has boolean logic but does not use the same syntax as other boolean options. You can use this option to instruct JPublisher to not use schema names to qualify SQL names that are referenced in wrapper classes. (By default, JPublisher uses schema names to qualify SQL names.) To enable the option (to disable the use of schema names), enter the option name, "-omit_schema_names
", on the command line, but do not attempt to set "-omit_schema_names=true
" or "-omit_schema_names=false
". See "Omission of Schema Name from Name References (-omit_schema_names)" for additional information.
The following sections describe the basic categories of publishing that the JPublisher utility supports:
Using JPublisher to publish SQL objects or collections as Java classes is straightforward. This section provides examples of this for the OE
(Order Entry) schema that is part of the Oracle Database sample schema. (See Oracle Database Sample Schemas for detailed information.) If you do not have the sample schema installed, but have your own object types that you would like to publish, then replace the user name, password, and object names with your own.
Assuming that the password for the OE
schema is OE
, use the following command to publish the SQL object type CATEGORY_TYP
(where %
is the system prompt):
% jpub -user=OE/OE -sql=CATEGORY_TYP:CategoryTyp
Note: See "Declaration of Object Types and Packages to Translate (-sql)" for more information about the-sql option. |
Use the JPublisher -user
option to specify the user name (schema name) and password. The -sql
option specifies the types to be published. CATEGORY_TYP
is the name of the SQL type and, separated by a colon (":"), CategoryTyp
is the name of the corresponding Java class to be generated. JPublisher echoes to the standard output the names of the SQL types that it is publishing:
OE.CATEGORY_TYP
When you list the files in your current directory, notice that in addition to the file CategoryTyp.java
, JPublisher has also generated the file CategoryTypeRef.java
. This represents a strongly typed wrapper class for SQL object references to OE.CATEGORY_TYP
. Both files are ready to be compiled with the Java compiler, javac
.
Here is another example, for the type CUSTOMER_TYP
, using the shorthand -u
(followed by a space) for "-user=
" and -s
(followed by a space) for "-sql=
":
% jpub -u OE/OE -s CUSTOMER_TYP:CustomerTyp
JPublisher reports a list of SQL object types, as follows, because whenever it encounters an object type for the first time (whether through an attribute, an object reference, or a collection that has element types that themselves are objects or collections), it automatically generates a wrapper class for that type as well.
OE.CUSTOMER_TYP OE.CORPORATE_CUSTOMER_TYP OE.CUST_ADDRESS_TYP OE.PHONE_LIST_TYP OE.ORDER_LIST_TYP OE.ORDER_TYP OE.ORDER_ITEM_LIST_TYP OE.ORDER_ITEM_TYP OE.PRODUCT_INFORMATION_TYP OE.INVENTORY_LIST_TYP OE.INVENTORY_TYP OE.WAREHOUSE_TYP
Two source files are generated for each object type in this example: 1) source file for a Java class, such as CustomerTyp
, to represent instances of the object type; and 2) source file for a reference class, such as CustomerTypeRef
, to represent references to the object type. You may also have noticed the naming scheme that JPublisher uses by default: the SQL type OE.PRODUCT_INFORMATION_TYP
turns into a Java class ProductInformationTyp
, for example.
Even though JPublisher automatically generates wrapper classes for embedded types, it does not do so for subtypes of given object types. In this case, you have to explicitly enumerate all the subtypes that you want to have published. The CATEGORY_TYP
type has three subtypes: LEAF_CATEGORY_TYP
, COMPOSITE_CATEGORY_TYP
, and CATALOG_TYP
. The following is a single wraparound JPublisher command line to publish these object types.
% jpub -u OE/OE -s COMPOSITE_CATEGORY_TYP:CompositeCategoryTyp -s LEAF_CATEGORY_TYP:LeafCategoryTyp,CATALOG_TYP:CatalogTyp
Here is the JPublisher output, listing the processed types:
OE.COMPOSITE_CATEGORY_TYP OE.SUBCATEGORY_REF_LIST_TYP OE.LEAF_CATEGORY_TYP OE.CATALOG_TYP OE.CATEGORY_TYP OE.PRODUCT_REF_LIST_TYP
Note the following:
If you want to unparse several types, you can list them all together in the -sql
(-s
) option, separated by commas, or you can supply several -sql
options on the command line, or you can do both.
Although JPublisher does not automatically generate wrapper classes for all subtypes, it does generate them for all supertypes.
For SQL objects with methods (stored procedures), such as CATALOG_TYP
, JPublisher uses SQLJ classes, meaning Java classes that use the SQLJ runtime during execution, to implement the wrapper methods. In Oracle Database 10g, the use of SQLJ classes, as opposed to regular Java classes, is invisible to you unless you use one of the backward compatibility modes.
Note: In Oracle9i or Oracle8i releases, the generation of SQLJ classes results in the creation of visible.sqlj source files. In this example, it results in .sqlj source files corresponding to CATALOG_TYP and its three subtypes. This is also true in Oracle Database 10g if you set the JPublisher -compatible flag to a value of 8i , both8i , 9i , or sqlj .
For any of these modes, you can use the JPublisher See "Backward Compatibility Option" and "Option to Access SQLJ Functionality" for information about these options. |
If the code that JPublisher generates does not give you the functionality or behavior you want, then you can extend generated wrapper classes to override or complement their functionality. Consider the following example:
% jpub -u OE/OE -s WAREHOUSE_TYP:JPubWarehouse:MyWarehouse
Here is the JPublisher output:
OE.WAREHOUSE_TYP
With this command, JPublisher generates both JPubWarehouse.java
and MyWarehouse.java
. The file JPubWarehouse.java
is regenerated every time you rerun this command. The file MyWarehouse.java
is created to be customized by you, and will not be overwritten by future runs of this JPublisher invocation. You can add new methods in MyWarehouse.java
, override the method implementations from JPubWarehouse.java
, or both. The class that is used to materialize WAREHOUSE_TYP
instances in Java is the specialized class MyWarehouse
. If you want user-specific subclasses for all types in an object type hierarchy, then you must specify "triplets" of the form SQL_TYPE
:
JPubClass
:
UserClass
, as shown in the preceding JPublisher command, for all members of the hierarchy.
Once you have generated and compiled Java wrapper classes with JPublisher, using them is fairly straightforward. You can use the object wrappers directly.
Note: The preceding examples using theOE schema are for illustrative purposes only and may not be completely up-to-date regarding the composition of the schema. |
The following SQLJ class calls a PL/SQL stored procedure. Assume that register_warehouse
takes a WAREHOUSE_TYP
instance as an IN OUT
parameter. (A code comment shows the corresponding #sql
command. By default, JPublisher generates and translates the SQLJ code automatically.) See the next section, "Publishing PL/SQL Packages", for a discussion of wrapper methods and the problems posed by OUT
and IN OUT
arguments.
java.math.BigDecimal location = new java.math.BigDecimal(10); java.math.BigDecimal warehouseId = new java.math.BigDecimal(10); MyWarehouse w = new MyWarehouse(warehouseId,"Industrial Park",location); // ************************************************************ // #sql { call register_warehouse(:INOUT w) }; // ************************************************************ // // declare temps oracle.jdbc.OracleCallableStatement __sJT_st = null; sqlj.runtime.ref.DefaultContext __sJT_cc = sqlj.runtime.ref.DefaultContext.getDefaultContext(); if (__sJT_cc==null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX(); sqlj.runtime.ExecutionContext.OracleContext __sJT_ec = ((__sJT_cc.getExecutionContext()==null) ? sqlj.runtime.ExecutionContext.raiseNullExecCtx() : __sJT_cc.getExecutionContext().getOracleContext()); try { String theSqlTS = "BEGIN register_warehouse( :1 ) \n; END;"; __sJT_st = __sJT_ec.prepareOracleCall(__sJT_cc,"0RegisterWarehouse",theSqlTS); if (__sJT_ec.isNew()) { __sJT_st.registerOutParameter(1,2002,"OE.WAREHOUSE_TYP"); } // set IN parameters if (w==null) __sJT_st.setNull(1,2002,"OE.WAREHOUSE_TYP"); else __sJT_st.setORAData(1,w); // execute statement __sJT_ec.oracleExecuteUpdate(); // retrieve OUT parameters w = (MyWarehouse)__sJT_st.getORAData(1,MyWarehouse.getORADataFactory()); } finally { __sJT_ec.oracleClose(); }
In JDBC, you typically register the relationship between the SQL type name and the corresponding Java class in the type map for your connection instance. This is required once for each connection, as in the following example:
java.util.Map typeMap = conn.getTypeMap(); typeMap.put("OE.WAREHOUSE_TYP", MyWarehouse.class); conn.setTypeMap(typeMap);
The following JDBC code is equivalent to the JPublisher output (translated SQLJ code) shown previously:
CallableStatement cs = conn.prepareCall("{call register_warehouse(?)}"); ((OracleCallableStatement)cs).registerOutParameter (1, Oracle.jdbc.OracleTypes.STRUCT,"OE.WAREHOUSE_TYP"); cs.setObject(w); cs.executeUpdate(); w = cs.getObject(1);
In addition to mapping SQL objects, you may want to encapsulate entire PL/SQL packages as Java classes. JPublisher offers functionality to create Java wrapper methods for the stored procedures of a PL/SQL package.
The concept of representing PL/SQL stored procedures as Java methods presents a problem, however. Arguments to such functions or procedures may use the PL/SQL mode OUT
or IN OUT
, but there are no equivalent modes for passing arguments in Java. A method that takes an int
argument, for example, is not able to modify this argument in such a way that its callers can receive a new value for it. As a workaround, JPublisher can generate single-element arrays for OUT
and IN OUT
arguments. For an array int[] abc
, for example, the input value is provided in abc[0]
, and the modified output value is also returned in abc[0]
. JPublisher also uses a similar pattern when generating code for SQL object type methods.
For additional information about the array mechanism and other mechanisms for handling OUT
or IN OUT
parameters, see "JPublisher Treatment of Output Parameters".
Note: If your stored procedures use types that are specific to PL/SQL and are not supported by JDBC, special steps are required to map these arguments to SQL and then to Java. See "Support for PL/SQL Datatypes". |
The following command line publishes the SYS.DBMS_LOB
package into Java:
% jpub -u SCOTT/TIGER -s SYS.DBMS_LOB:DbmsLob
Here is the JPublisher output:
SYS.DBMS_LOB
Because DBMS_LOB
is publicly visible, you can access it from a different schema, such as SCOTT
. Note that this JPublisher invocation creates a SQLJ class in DbmsLob.java
that contains the calls to the PL/SQL package. The generated Java methods are actually all instance methods. The idea is that you create an instance of the package using a JDBC connection or a SQLJ connection context and then call the methods on that instance.
When you examine the generated code, notice that JPublisher has generated java.lang.Integer
as arguments to various methods. Using Java object types such as Integer
instead of Java primitive types such as int
permits you to represent SQL NULL
values directly as Java null
s, and JPublisher generates these by default. However, for the DBMS_LOB
package, int
is preferable over the object type Integer
. The following modified JPublisher invocation accomplishes this through the -numbertypes
option.
% jpub -numbertypes=jdbc -u SCOTT/TIGER -s SYS.DBMS_LOB:DbmsLob
Here is the JPublisher output:
SYS.DBMS_LOB
See "Mappings For Numeric Types (-numbertypes)" for information about that option.
JPublisher also enables you to generate a wrapper class for the functions and procedures at the SQL top level. Use the special package name TOPLEVEL
, as in the following example:
% jpub -u SCOTT/TIGER -s TOPLEVEL:SQLTopLevel
Here is the JPublisher output:
SCOTT.top-level_scope
A warning appears if there are no stored functions or procedures in the SQL top-level scope.
Oracle Database 10g introduces the native Java interface—new features for calls to server-side Java code. Previously, calling Java stored procedures and functions from a database client required JDBC calls to associated PL/SQL wrappers. Each PL/SQL wrapper had to be manually published with a SQL signature and a Java implementation. This process had the following disadvantages:
The signatures permitted only Java types that had direct SQL equivalents.
Exceptions issued in Java were not properly returned.
The JPublisher -java
option provides functionality to avoid these disadvantages.
To remedy the deficiencies of JDBC calls to associated PL/SQL wrappers, the -java
option makes convenient use of an API for direct invocation of static Java methods. This functionality is also useful for Web services.
The functionality of the -java
option mirrors that of the -sql
option, creating a client-side Java stub class to access a server-side Java class, in contrast to creating a client-side Java class to access a server-side SQL object or PL/SQL package. The client-side stub class mirrors the server-side class and includes the following features:
Methods corresponding to the public static methods of the server class
Two constructors: one that takes a JDBC connection and one that takes the SQLJ default connection context instance
At runtime, the stub class is instantiated with a JDBC connection. Calls to its methods result in calls to the corresponding methods of the server-side class. Any Java types used in these published methods must be primitive or serializable.
As an example, assume that you want to call the following method in the server:
public String oracle.sqlj.checker.JdbcVersion.to_string();
Use the -java
setting in the following JPublisher command:
% jpub -u scott/tiger -url=jdbc:oracle:oci:@ -java=oracle.sqlj.checker.JdbcVersion
Note that for invocation of server-side Java, you must provide information for the database connection.
See "Declaration of Server-Side Java Classes to Translate (-java)" for information about -java
option syntax.
The JPublisher -sqlstatement
option enables you to publish SQL queries (SELECT
statements) or DML statements (INSERT
, UPDATE
, or DELETE
statements) as Java methods. This functionality is of potential use for Web services, but is more generally useful as well.
Specify the following through -sqlstatement
settings:
Java class in which the method will be published (-sqlstatement.class=
classname
)
SQL statement and desired corresponding Java method name (-sqlstatement.
methodname
=
sqlstatement
)
Whether JPublisher should generate a method that returns a generic java.sql.ResultSet
instance, a method that returns an array of JavaBeans, or both methods (-sqlstatement.return=resultset|beans|both
)
Consider the following -sqlstatement
settings:
-sqlstatement.class=SqlStatement -sqlstatement.getEmp="select ename from emp where empno=:{myno NUMBER}"
JPublisher generates a class named SqlStatement
with the following method:
public static GetEmpRow[] getEmpBeans(int myno) {...}
See "Declaration of SQL Statements to Translate (-sqlstatement)" for syntax information and a complete example.
Given a Web Services Description Language (WSDL) document at a specified URL, JPublisher directs the generation of Web services client proxy classes and generates appropriate Java and PL/SQL wrappers for Web services call-outs from the database. Classes to generate and process are determined from the WSDL document. JPublisher executes the following steps:
Invokes the Oracle Database Web services assembler tool to produce Web services client proxy classes based on the WSDL document.
As appropriate or necessary, creates Java wrapper classes for the Web services client proxy classes. For each proxy class that has instance methods (as is typical), a wrapper class is necessary to expose the instance methods as static methods.
Creates PL/SQL wrappers (call specs) for the generated classes, to make them accessible from PL/SQL.
Loads generated code into the database, unless you specify otherwise, and assuming you specify a database to connect to.
See "Options to Facilitate Web Services Call-Outs" for details.
The following sections offer a basic overview of JPublisher mappings and mapping categories:
JPublisher provides mappings from the following to Java classes:
User-defined SQL types (objects, collections, and OPAQUE types)
PL/SQL types
You can use an Oracle-specific implementation, a standard implementation, or a generic implementation in representing user-defined SQL types—such as objects, collections, object references, and OPAQUE types—in your Java program.
Here is a summary of these three approaches:
Use classes that implement the Oracle-specific ORAData
interface.
JPublisher generates classes that implement the oracle.sql.ORAData
interface. (You can also write them by hand, but this is generally not recommended.)
The ORAData
interface supports SQL objects, object references, collections, and OPAQUE types in a strongly typed way. That is, for each specific object, object reference, collection, or OPAQUE type in the database, there is a corresponding Java type.
See the next section, "Using Strongly Typed Object References for ORAData Implementations", for details about strongly typed object reference representations through the ORAData
interface.
Note: JPublisher generates classes for object reference, collection, and OPAQUE types only if it is generatingORAData classes. |
Use classes that implement the standard SQLData
interface, as described in the JDBC specification.
JPublisher generates classes for SQL object types that implement the java.sql.SQLData
interface. (You can also write them by hand, but this is generally not recommended. Note that if you write them by hand, or if you generate classes for an inheritance hierarchy of object types, your classes must be registered using a type map.)
When you use the SQLData
interface, all object reference types are represented generically as java.sql.Ref
, and all collection types are represented generically as java.sql.Array
. In addition, when using SQLData
, there is no mechanism for representing OPAQUE types.
Use oracle.sql.*
classes.
You can use the oracle.sql.*
classes to represent user-defined types generically. The class oracle.sql.STRUCT
represents all object types, the class oracle.sql.ARRAY
represents all VARRAY and nested table types, the class oracle.sql.REF
represents all object reference types, and the class oracle.sql.OPAQUE
represents all OPAQUE types. These classes are immutable in the same way that java.lang.String
is.
Choose this option for code that processes objects, collections, references, or OPAQUE types in a generic way. Unlike classes implementing ORAData
or SQLData
, oracle.sql.*
classes are not strongly typed.
In addition to strong typing, JPublisher-generated classes that implement ORAData
or SQLData
have the following advantages:
The classes are customized, rather than generic. You access attributes of an object using get
XXX
()
and set
XXX
()
methods named after the particular attributes of the object. Note that you must explicitly update the object in the database if there are any changes to its data.
The classes are mutable. You can generally modify attributes of an object or elements of a collection. The exception is that ORAData
classes representing object reference types are not mutable, because an object reference does not have any subcomponents that could be sensibly modified. You can, however, use the setValue()
method of a reference object to change the database value that the reference points to.
You can generate Java wrapper classes that are serializable or that have the toString()
method to print out the object together with its attribute values.
Compared to classes that implement SQLData
, classes that implement ORAData
are fundamentally more efficient, because ORAData
classes avoid unnecessary conversions to native Java types. For additional information about the SQLData
and ORAData
interfaces, including a comparison, see the Oracle Database JDBC Developer's Guide and Reference.
For Oracle ORAData
implementations, JPublisher always generates strongly typed object reference classes in contrast to using the weakly typed oracle.sql.REF
class. This is to provide greater type safety and to mirror the behavior in SQL, in which object references are strongly typed. The strongly typed classes (with names such as PersonRef
for references to PERSON
objects) are essentially wrappers for the oracle.sql.REF
class.
In these strongly typed REF
wrappers, a getValue()
method produces an instance of the SQL object that is referenced, in the form of an instance of the corresponding Java class (or, in the case of inheritance, perhaps as an instance of a subclass of the corresponding Java class). For example, if there is a PERSON
object type in the database, with a corresponding Person
Java class, there will also be a PersonRef
Java class. The getValue()
method of the PersonRef
class would return a Person
instance containing the data for a PERSON
object in the database. In addition, JPublisher also generates a static cast()
method on the PersonRef
class, permitting you to convert other typed references to a PersonRef
instance.
Whenever a SQL object type has an attribute that is an object reference, the Java class corresponding to the object type would have an attribute that is an instance of a Java class corresponding to the appropriate reference type. For example, if there is a PERSON
object with a MANAGER REF
attribute, then the corresponding Person
Java class will have a ManagerRef
attribute.
JDBC does not support PL/SQL-specific types—such as the BOOLEAN
type, PL/SQL RECORD types, and PL/SQL indexed-by table types—that are used in stored procedures or functions. (One exception is scalar PL/SQL indexed-by tables, which are currently supported in the client-side JDBC OCI driver only.) JPublisher provides the following workarounds for PL/SQL types:
JPublisher has a "type map" that you can use to specify the mapping for a PL/SQL type unsupported by JDBC.
For PL/SQL RECORD types or indexed-by tables types, you also have the choice of JPublisher automatically creating a SQL object type or SQL collection type, respectively, as a middle step in the mapping.
With either mechanism, JPublisher creates PL/SQL conversion functions or uses predefined conversion functions (typically in the SYS.SQLJUTL
package) to convert between a PL/SQL type and a corresponding SQL type. The conversion functions can be used in generated Java code that calls a stored procedure directly, or JPublisher can create a wrapper function around the PL/SQL stored procedure, where generated Java code calls the wrapper function, which calls the conversion functions. Either way, only SQL types are exposed to JDBC.
See "JPublisher User Type Map and Default Type Map" and "Support for PL/SQL Datatypes" for additional information.
JPublisher offers different categories of datatype mappings from SQL to Java. ("Options for Datatype Mappings" describes JPublisher options to specify these mappings.)
Each type mapping option has at least two possible values: jdbc
and oracle
. The -numbertypes
option has two additional alternatives: objectjdbc
and bigdecimal
.
The following sections describe these categories of mappings. For more information about datatype mappings, see Chapter 2.
In JDBC mapping, most numeric datatypes are mapped to Java primitive types, such as int
and float
, and DECIMAL
and NUMBER
are mapped to java.math.BigDecimal
. LOB types and other non-numeric built-in types are mapped to standard JDBC types, such as java.sql.Blob
and java.sql.Timestamp
. For object types, JPublisher generates SQLData
classes. Because predefined datatypes that are Oracle extensions (such as BFILE
and ROWID
) do not have JDBC mappings, only the oracle.sql.*
mapping is supported for these types.
The Java primitive types used in the JDBC mapping do not support null values and do not guard against integer overflow or floating-point loss of precision. If you are using the JDBC mapping and you attempt to call an accessor or method to get an attribute of a primitive type (short
, int
, float,
or double
) whose value is null
, then an exception is thrown. If the primitive type is short
or int
, then an exception is thrown if the value is too large to fit in a short
or int
variable.
In Object JDBC mapping, most numeric datatypes are mapped to Java wrapper classes, such as java.lang.Integer
and java.lang.Float
, and DECIMAL
and NUMBER
are mapped to java.math.BigDecimal
. This differs from the JDBC mapping only in that it does not use primitive types.
When you use the Object JDBC mapping, all your returned values are objects. If you attempt to get an attribute whose value is null
, then a null object is returned.
The Java wrapper classes used in the Object JDBC mapping do not guard against integer overflow or floating-point loss of precision. If you call an accessor method to get an attribute that maps to java.lang.Integer
, then an exception is thrown if the value is too large to fit.
Object JDBC is the default mapping for numeric types.
In BigDecimal
mapping, all numeric datatypes are mapped to java.math.BigDecimal
. This supports null values and large values.
In Oracle mapping, the numeric, LOB, or other built-in types are mapped to classes in the oracle.sql
package. For example, the DATE
type is mapped to oracle.sql.DATE
, and all numeric types are mapped to oracle.sql.NUMBER
. For object, collection, and object reference types, JPublisher generates ORAData
classes.
Because the Oracle mapping uses no primitive types, it can represent a null value as a Java null
in all cases. Because it uses the oracle.sql.NUMBER
class for all numeric types, it can represent the largest numeric values that can be stored in the database.
To publish database entities, JPublisher connects to the database and retrieves descriptions of SQL types, PL/SQL packages, or server-side Java classes that you specify on the command line or in an INPUT
file. By default, JPublisher connects to the database by using the Oracle JDBC OCI driver, which requires an Oracle client installation, including Oracle Net Services and required support files. If you do not have an Oracle client installation, then JPublisher can use the Oracle JDBC Thin driver.
JPublisher generates a Java class for each SQL type or PL/SQL package that it translates, and each server-side Java class that it processes. Generated classes include code required to read objects from and write objects to the database. When you deploy the generated JPublisher classes, your JDBC driver installation includes all the necessary runtime files. If JPublisher generates wrapper methods for stored procedures, then the classes that it produces use the SQLJ runtime during execution. In this case, which is typical, you must additionally have the SQLJ runtime library runtime12.jar
.
When you call a wrapper method on an instance of a class that was generated for a SQL object, the SQL value for the corresponding object is sent to the server along with any IN
or IN OUT
arguments. Then the method (stored procedure or function) is invoked, and the new object value is returned to the client along with any OUT
or IN OUT
arguments. Note that this results in a database round trip. If the method call only performs a simple state change on the object, there will be better performance if you write and use equivalent Java that affects the state change locally.
The number of classes that JPublisher produces depends on whether you request ORAData
classes or SQLData
classes.
To publish external Web services for access from inside a database, JPublisher accesses a specified WSDL document, directs the generation of appropriate client proxy classes, then generates wrapper classes, as necessary, and PL/SQL wrappers to allow Web services call-outs from PL/SQL.
The following subsections go into more detail:
In addition, see "Summary of the Publishing Process: Generation and Use of Output" for a graphical representation of the flow of input and output.
You can specify input options on the command line and in a JPublisher properties file. In addition to producing Java classes for the translated entities, JPublisher writes the names of the translated objects and packages to standard output. "JPublisher Options" describes all the JPublisher options.
In addition, you can use a file known as the JPublisher INPUT
file to specify the SQL types, PL/SQL packages, or server-side Java classes that JPublisher should publish. It also controls the naming of the generated packages and classes. "INPUT File Structure and Syntax" describes INPUT
file syntax.
To use a properties file to specify option settings, specify the name of the properties file on the command line, using the -props
option. JPublisher processes a properties file as if its contents were inserted in sequence on the command line at the point of the -props
option. For additional flexibility, properties files can also be SQL script files in which the JPublisher directives are embedded in SQL comments. For more information about properties file and their formats, see "Properties File Structure and Syntax".
This section describes JPublisher output for user-defined object types, user-defined collection types, OPAQUE types, PL/SQL packages, server-side Java classes, and SQL queries or DML statements.
Note: Be aware that when JPublisher publishes a database entity, such as a SQL type or PL/SQL package, it also generates classes for any types that are referenced by the entity. If, for example, a stored procedure in a PL/SQL package being published uses a SQL object type as an argument, a class will be generated to map to that SQL object type. |
When you run JPublisher for a user-defined object type and you request ORAData
classes, JPublisher creates the following:
An object class that represents instances of the Oracle object type in your Java program
For each object type, JPublisher generates a type
.java
file for the class code, such as Employee.java
for the Oracle object type EMPLOYEE
.
Optionally, a stub subclass, named as specified in your JPublisher settings, that you can modify as desired for custom functionality
Optionally, an interface for the generated class or subclass to implement
A related reference (REF) class for object references
JPublisher generates a type
Ref.java
file for the code for the REF class associated with the object type, such as EmployeeRef.java
for references of the Oracle object type EMPLOYEE
.
Java classes for any object or collection or OPAQUE attributes nested directly or indirectly within the top-level object
This is necessary so that attributes can be materialized in Java whenever an instance of the top-level class is materialized. If an attribute type, such as a SQL OPAQUE type or a PL/SQL type, has been pre-mapped, then JPublisher uses the target Java type from the map.
Notes:
|
If you request SQLData
classes instead, JPublisher does not generate the object reference class and does not generate classes for nested collection attributes or for OPAQUE attributes.
When you run JPublisher for a user-defined collection type, you must request ORAData
classes. JPublisher creates the following:
A collection class to act as a type definition to correspond to your Oracle collection type
For each collection type (nested table or VARRAY) it translates, JPublisher generates a
type
.java
file. For nested tables, the generated class has methods to get and set the nested table as an entire array and to get and set individual elements of the table. JPublisher translates collection types when generating ORAData
classes, but not when generating SQLData
classes.
If the elements of the collection are objects, a Java class for the element type, and Java classes for any object or collection attributes nested directly or indirectly within the element type
This is necessary so object elements can be materialized in Java whenever an instance of the collection is materialized.
Optionally, an interface that is implemented by the generated type
Note: Unlike for object types, you do not have the option of generating user subclasses for collection types. |
When you run JPublisher for an OPAQUE type, you must request ORAData
classes. JPublisher creates a Java class that acts as a wrapper for the OPAQUE type, providing Java versions of the OPAQUE type methods as well as protected
APIs to access the representation of the OPAQUE type in a subclass.
Typically, however, Java wrapper classes for SQL OPAQUE types are furnished by the provider of the OPAQUE type, such as, for example, oracle.xdb.XMLType
for the SQL OPAQUE type SYS.XMLTYPE
. In this case, ensure that the correspondence between the SQL type and the Java type is predefined to JPublisher through the type map.
When you run JPublisher for a PL/SQL package, it creates a Java class with wrapper methods that invoke the stored procedures of the package on the server. IN
arguments for the methods are transmitted from the client to the server, and OUT
arguments and results are returned from the server to the client.
When you run JPublisher for a general-use server-side Java class, it creates source code, type
.java
, for a client-side stub class that mirrors the server class. When you call the client-side methods, the corresponding server-side methods are called transparently.
For Web services call-outs, JPublisher typically generates wrapper classes for the server-side client proxy classes, as a bridge to the corresponding PL/SQL wrappers. This is necessary to publish any proxy class instance methods as static methods, because PL/SQL does not support instance methods.
When you run JPublisher for a SQL query or DML statement (SELECT
, UPDATE
, INSERT
, or DELETE
), it creates the following:
A Java class that implements the method that executes the SQL statement
Optionally, a Java stub subclass, named as specified in your JPublisher settings, that you can modify as desired for custom functionality
Optionally, a Java interface for the generated class or subclass to implement
Depending on your usage, JPublisher may generate a PL/SQL package and associated PL/SQL scripts.
JPublisher typically generates a PL/SQL package with PL/SQL code for any of the following:
PL/SQL call specs for generated Java methods
PL/SQL conversion functions and wrapper functions to support PL/SQL types
PL/SQL table functions
Conversion functions, and optionally wrapper functions, are employed to map PL/SQL types used in the calling sequences of any stored procedures that JPublisher translates. The functions convert between PL/SQL types and corresponding SQL types, given that JDBC does not generally support PL/SQL types.
JPublisher generates PL/SQL scripts as follows:
A "wrapper script" to create the PL/SQL package and any necessary SQL types
A script to grant permission to execute the wrapper script
A script to revoke permission to execute the wrapper script
A script to drop the package and types created by the wrapper script
This section discusses the basic steps in using JPublisher, summarizes the command-line syntax, and concludes with a more detailed description of a sample translation. The following topics are covered:
This section lists the basic steps, illustrated in Figure 1-1 that follows, for publishing specified SQL types, PL/SQL packages, or server-side Java classes.
Run JPublisher with input from the command line, properties file, and INPUT
file, as desired.
JPublisher accesses the database to which it is attached to obtain definitions of SQL or PL/SQL entities that you specified for publishing.
JPublisher generates .java
or .sqlj
source files, as appropriate, depending primarily on whether wrapper methods are created for stored procedures.
By default, JPublisher invokes the SQLJ translator (provided as part of the JPublisher product) to translate .sqlj
files into .java
files.
By default, the SQLJ translator (or JPublisher, for non-SQLJ classes) invokes the Java compiler to compile .java
files into .class
files.
JPublisher outputs PL/SQL wrappers and scripts (.sql
files), as appropriate, in addition to the .class
files. There is a script to create the PL/SQL wrapper package and any necessary SQL types (such as types to map to PL/SQL types), a script to drop these entities, and scripts to grant or revoke required privileges.
In the case of proxy class generation (through the -proxywsdl
or -proxyclasses
option), JPublisher can load generated PL/SQL wrappers and scripts into the database to which it is connected, for execution in the database PL/SQL engine.
By default, JPublisher loads generated Java classes for Web services call-outs into the database to which it is connected, for execution in the database JVM. JPublisher-generated classes other than those for Web services call-outs typically execute in a client or middle-tier JVM. You may also have your own classes, such as subclasses of JPublisher-generated classes, that would typically execute in a client or middle-tier JVM.
Figure 1-1 Translating and Using JPublisher-Generated Code
On most operating systems, you invoke JPublisher on the command line, typing jpub
followed by a series of options settings, as follows:
% jpub -option1=value1 -option2=value2 ...
JPublisher responds by connecting to the database and obtaining the declarations of the types or packages you specify, then generating one or more custom Java classes (SQLJ classes or non-SQLJ classes, as appropriate) and writing the names of the translated object types or PL/SQL packages to standard output.
Here is an example of a (single wraparound) command that invokes JPublisher:
% jpub -user=scott/tiger -input=demoin -numbertypes=oracle -usertypes=oracle -dir=demo -d=demo -package=corp
Enter the command on one command line, allowing it to wrap as necessary. For clarity, this chapter refers to the input file specified by the -input
option as the INPUT
file (to distinguish it from any other kinds of input files).
This command directs JPublisher to connect to the database with user name SCOTT
and password TIGER
and to translate datatypes to Java classes, based on instructions in the INPUT
file demoin
. The -numbertypes=oracle
option directs JPublisher to map object attribute types to Java classes supplied by Oracle, and the -usertypes=oracle
option directs JPublisher to generate Oracle-specific ORAData
classes. JPublisher places the classes that it generates in the package corp
under the directory demo
.
JPublisher also supports specification of .java
files (or .sqlj
files, if you are using SQLJ source files directly) on the JPublisher command line. The specified files are translated and compiled in addition to any JPublisher-generated files. For example:
% jpub ...options... Myclass.java
Notes:
|
This section provides a sample JPublisher translation of a user-defined object type. At this point, do not worry about the details of the code JPublisher generates. You can find more information about JPublisher input and output files, options, datatype mappings, and translation later in this manual.
Note: For more examples, go toORACLE_HOME /sqlj/demo/jpub in your Oracle installation. |
Create the object type EMPLOYEE
:
CREATE TYPE employee AS OBJECT ( name VARCHAR2(30), empno INTEGER, deptno NUMBER, hiredate DATE, salary REAL );
The INTEGER
, NUMBER
, and REAL
types are all stored in the database as NUMBER
types, but after translation they have different representations in the Java program, based on your setting of the -numbertypes
option.
Assume JPublisher translates the types according to the following (wraparound) command line:
% jpub -user=scott/tiger -dir=demo -numbertypes=objectjdbc -builtintypes=jdbc -package=corp -case=mixed -sql=Employee
"JPublisher Options" describes each of these options in detail.
Note that because the EMPLOYEE
object type does not define any methods, JPublisher generates a non-SQLJ class.
Because -dir=demo
and -package=corp
were specified on the JPublisher command line, the translated class Employee
is written to Employee.java
in the following location (for a UNIX system):
./demo/corp/Employee.java
The Employee.java
class file would contain the code shown in the following example.
Note: The details of the code JPublisher generates are subject to change. In particular, non-public methods, non-public fields, and all method bodies may be generated differently. |
package corp; import java.sql.SQLException; import java.sql.Connection; import oracle.jdbc.OracleTypes; import oracle.sql.ORAData; import oracle.sql.ORADataFactory; import oracle.sql.Datum; import oracle.sql.STRUCT; import oracle.jpub.runtime.MutableStruct; public class Employee implements ORAData, ORADataFactory { public static final String _SQL_NAME = "SCOTT.EMPLOYEE"; public static final int _SQL_TYPECODE = OracleTypes.STRUCT; protected MutableStruct _struct; private static int[] _sqlType = { 12,4,2,91,7 }; private static ORADataFactory[] _factory = new ORADataFactory[5]; protected static final Employee _EmployeeFactory = new Employee(false); public static ORADataFactory getORADataFactory() { return _EmployeeFactory; } /* constructor */ protected Employee(boolean init) { if(init) _struct = new MutableStruct(new Object[5], _sqlType, _factory); } public Employee() { this(true); } public Employee(String name, Integer empno, java.math.BigDecimal deptno, java.sql.Timestamp hiredate, Float salary) throws SQLException { this(true); setName(name); setEmpno(empno); setDeptno(deptno); setHiredate(hiredate); setSalary(salary); } /* ORAData interface */ public Datum toDatum(Connection c) throws SQLException { return _struct.toDatum(c, _SQL_NAME); } /* ORADataFactory interface */ public ORAData create(Datum d, int sqlType) throws SQLException { return create(null, d, sqlType); } protected ORAData create(Employee o, Datum d, int sqlType) throws SQLException { if (d == null) return null; if (o == null) o = new Employee(false); o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory); return o; } /* accessor methods */ public String getName() throws SQLException { return (String) _struct.getAttribute(0); } public void setName(String name) throws SQLException { _struct.setAttribute(0, name); } public Integer getEmpno() throws SQLException { return (Integer) _struct.getAttribute(1); } public void setEmpno(Integer empno) throws SQLException { _struct.setAttribute(1, empno); } public java.math.BigDecimal getDeptno() throws SQLException { return (java.math.BigDecimal) _struct.getAttribute(2); } public void setDeptno(java.math.BigDecimal deptno) throws SQLException { _struct.setAttribute(2, deptno); } public java.sql.Timestamp getHiredate() throws SQLException { return (java.sql.Timestamp) _struct.getAttribute(3); } public void setHiredate(java.sql.Timestamp hiredate) throws SQLException { _struct.setAttribute(3, hiredate); } public Float getSalary() throws SQLException { return (Float) _struct.getAttribute(4); } public void setSalary(Float salary) throws SQLException { _struct.setAttribute(4, salary); } }
JPublisher also generates object constructors based on the object attributes.
Additional private
or public
methods may be generated with other option settings. For example, the setting -serializable=true
results in the object wrapper class implementing the interface java.io.Serializable
and in the generation of private writeObject()
and private readObject()
methods. The setting -tostring=true
results in the additional generation of a public toString()
method.
There is a protected _struct
field in JPublisher-generated code for SQL object types. This is an instance of the internal class oracle.jpub.runtime.MutableStruct
; this instance contains the data in original SQL format. In general, you should never reference this field directly. Instead, use the setting -methods=always
or -methods=named
, as necessary, to ensure that JPublisher produces setFrom()
and setValueFrom()
methods, then use these methods when extending a class. See "The setFrom(), setValueFrom(), and setContextFrom() Methods".
JPublisher generates SQLJ classes instead of non-SQLJ classes in the following circumstances:
The SQL object being published has methods, and the setting -methods=false
is not specified.
A PL/SQL package, stored procedure, query, or DML statement is published, and the setting -methods=false
is not specified.
Additionally:
If a SQLJ class is created for a type definition, then a SQLJ class is also created for the corresponding REF definition.
If a SQLJ class is created for a base class, then SQLJ classes are also created for any subclasses.
(In a backward compatibility mode, this means that JPublisher generates .sqlj
files instead of .java
files.)
Note that the JPublisher version provided with Oracle8i generates implementations of the now-deprecated CustomDatum
and CustomDatumFactory
interfaces, instead of ORAData
and ORADataFactory
. In fact, it is still possible to do this through the JPublisher -compatible
option, and this is required if you are using an Oracle8i JDBC driver.
JPublisher also generates an EmployeeRef.java
class. The source code is displayed here:
package corp; import java.sql.SQLException; import java.sql.Connection; import oracle.jdbc.OracleTypes; import oracle.sql.ORAData; import oracle.sql.ORADataFactory; import oracle.sql.Datum; import oracle.sql.REF; import oracle.sql.STRUCT; public class EmployeeRef implements ORAData, ORADataFactory { public static final String _SQL_BASETYPE = "SCOTT.EMPLOYEE"; public static final int _SQL_TYPECODE = OracleTypes.REF; REF _ref; private static final EmployeeRef _EmployeeRefFactory = new EmployeeRef(); public static ORADataFactory getORADataFactory() { return _EmployeeRefFactory; } /* constructor */ public EmployeeRef() { } /* ORAData interface */ public Datum toDatum(Connection c) throws SQLException { return _ref; } /* ORADataFactory interface */ public ORAData create(Datum d, int sqlType) throws SQLException { if (d == null) return null; EmployeeRef r = new EmployeeRef(); r._ref = (REF) d; return r; } public static EmployeeRef cast(ORAData o) throws SQLException { if (o == null) return null; try { return (EmployeeRef) getORADataFactory().create(o.toDatum(null), OracleTypes.REF); } catch (Exception exn) { throw new SQLException("Unable to convert "+o.getClass().getName()+" to EmployeeRef: "+exn.toString()); } } public Employee getValue() throws SQLException { return (Employee) Employee.getORADataFactory().create( _ref.getSTRUCT(), OracleTypes.REF); } public void setValue(Employee c) throws SQLException { _ref.setValue((STRUCT) c.toDatum(_ref.getJavaSqlConnection())); } }
Note that JPublisher also generates a public static cast()
method to cast from other strongly typed references into a strongly typed reference instance.