In step 4.4 of the OrindaBuild user interface you can create a
class and matching interface that extend the DAO
Factory class. These service classes provide stateless methods that
can be used to call PL/SQL procedures or issue SQL statements as part
of a web service implemented using a tool such as Apache Axis. The
blue section of the diagram below
shows where OrindaBuild generated Java source code fits in:

OrindaBuild will generate Java Wrapper classes for each procedure,
function and SQL statement you select in the user interface. It then
creates a Data Access Object class that hands out live copies of the
generated classes. The Data Access Object class is extended to create a
Web Service Implementation class. In addition to providing stateless
calls to the wrapper classes it translates the Java data types used
into the subset that work with serialization and uses special classes
to hold the output of procedures that have work than one output
parameter. Because this class contains several public methods that we
wouldn't want to turn into a service we also create a Web Service
Interface class that lists the methods we want access.
| Class Name |
Description |
| Core Web Services
Classes |
|
| DAOFactoryServiceInterface.java
|
This
is a Java interface that contains only those methods that we want to be
part of our web service. It exists because DAOFactoryServiceImpl.java
will often contain methods that are public but not intended for use in
a web service. Rather than telling your version of Java2WSDL
which public methods are intended for use by a web service it's a lot
simpler to list the service methods in a Java interface and run Java2WSDL
against the interface. 'DAOFactoryServiceInterface' is a default name. The actual name can be set in step 4.4. An example of this file is available here. |
| DAOFactoryServiceImpl.java | This class extends DAOFactory.java by adding 'service' methods for each PL/SQL procedure and SQL statement selected by the user. It also translates the data types used by DAOFactory.java to ones that are compaible with the serialization protocols used by web services. 'DAOFactoryServiceImpl' is a default name. The actual name is set in step 4.4. An example of this file is available here. |
| DAOFactoryServiceException.java |
This is a special Exception that is used when errors are encountered by the service method. An example of this class can be found here. |
| Classes used to
represent Cursors when the fields in the cursor aren't known at compile
time. |
|
| WsdlRowSet.java |
This class represents the result of a Query. It consists of a list of column names and one WsdlRow for each row returned. This class has no methods other than a constructor. An example can be found here. |
| WsdlRow.java | This class represents a single row returned by a query. It consists of an array of WsdlElement. This class has no methods other than a constructor. An example can be found here. |
| WsdlElement.java | This class represents a column in a row returned by a query. This class has no methods other than a constructor. An example can be found here. |
| Classes used when more
than one value is returned by a procedure. |
|
| plsql/*Return.java |
If a service method returns more
than one parameter they will be stored together in a class in the plsql
subdirectory whose name ends in 'Return.java'. This class has no
methods other than a constructor. An example of a Return class for the
example procedure 'getLists'
can be found here. |
| Classes used to
represent records. |
|
| plsql/*Attrs.java |
These classes represent records that are used as parameters
for PL/SQL procedures and functions. |
In step 4.4 of the OrindaBuild user interface you can define a number
of options that alter the generated web service code:
| Option |
Description |
| Number type used by service |
All
numbers used by the service classes will be of the same data type. The
available types are: |
| Always release database
connection after call |
If selected the DAOFactory classes's 'relaseConnection' method will be called at the end of each service method call |
| Add pre call code stubs |
If
selected an additional method called 'doPreServiceEvent'
is added to the class to assist users who want to customize generated
code. |
| Add post call code stubs |
If selected an additional method called 'doPostServiceEvent' is added to the class to assist users who want to customize generated code. |
| Uploaded BFILE
naming is abstract |
Creating new BFILE's
represents a challange when working in a web services environment. See
the section on BFILES for
information on how
OrindaBuild can do this. |
The table
below lists the methods you can expect to find in a
DAOFactoryServiceImpl class
and explains what they are for. Methods that are part of the base
DAOFactory class are here.
| Method
Name |
Purpose |
Comment |
| Constructors |
||
| DAOFactoryServiceImpl() |
Default Constructor - calls parent classes
null parameter constructor. |
The default constructor calls the parent classes null parameter constructor. |
| Event Methods - Allow the user to alter the behaviour of generated code. | ||
| doPreServiceEvent() |
Execute additional user defined code. |
Optional. By extending DAOFactoryServiceImpl and overiding these methods uses can add custom behaviour to generated code. |
| doPostServiceEvent() | Execute additional user defined code. | |
| setAlwaysReleaseResourcesFlag() | Controls whether database resources are released at the end of each call. | Default value is controlled by user interface |
| Conversion and File IO
Methods |
||
| createBFILEarrayFromByteArray() |
Turn an array of byte[] into an
array of oracle.sql.BFILE |
This
method used createNewBfilePointer().
See the section on BFILES for
further
information. |
| createBLOBarrayFromByteArray() |
Turn an array of byte[] into an array of oracle.sql.BLOB | These
methods rely on the temporary LOB functionality introduced in Oracle
V9.0.1. |
| createCLOBarrayFromByteArray() |
Turn an array of byte[] into an array of oracle.sql.CLOB | |
| createByteArrayFromBFILEArray() |
Unloads an oracle.sql.BFILE into
a byte[]. |
These
methods unload oracle LOB objects into byte arrays suitable for
serialization. |
| createByteArrayFromBLOBArray() |
Unloads an oracle.sql.BLOB into a byte[]. | |
| createByteArrayFromCLOBArray() |
Unloads an oracle.sql.CLOB into a byte[]. | |
| createBigDecimalArrayFromIndexByTable() |
Turns an 'index by' table into
an array of numbers |
These
methods are used by generated code for working with INDEX BY Tables. |
| createStringArrayFromIndexByTable() |
Turns an 'index by' table into
an array of Strings |
|
| createIndexByTableFromBigDecimalArray() |
Turns an array of numbers into
an 'index by' table. |
|
| createIndexByTableFromStringArray() |
Turns an array of Strings into an 'index by' table. | |
| loadByteArrayIntoFile() |
Returns a java.io.File that
contains an array of byte[]. |
These
are generic IO methods that are needed because serialziation prefers
byte[] to java.io.File. |
| loadFileIntoByteArray() |
Returns a byte array that
respresents the contents of a java.io.File. |
|
| createWSDLRowset() |
Turns a com.orindasoft.pub.ReadOnlyRowSet
into a WSDLRowSet. |
com.orindasoft.pub.ReadOnlyRowSet
is unsuitable for serialization. |
| BFILE Creation Methods
- Exist when the web services code is trying to call procedures or
functions that insert BFILES. See below. |
||
| setOracleDirectoryDbName() |
Sets the Oracle Directory name
to be used when creating BFILES. The value entered should be the same
as the column DIRECTORY_NAME in the ALL_DIRECTORIES data
dictionary view. |
Generated code that inserts
BFILES will throw an exception if these methods have not been called
prior to the execution of the procedure. Both DB Name and OS Name must
refer to the same OS directory. |
| setOracleDirectoryOsName() |
Sets the Oracle Directory name
to be used when creating BFILES. The
value entered should be the same as the column DIRECTORY_PATH in
the
ALL_DIRECTORIES data dictionary view. |
|
| createNewBfilePointer() |
Creates an oracle.sql.BFILE
object. |
Involves a database access. |
| createNewBfileName() |
Return an array of Strings that
collectivly represent a BFILE. |
|
| [abstract]
getArbitraryGeneratedBfileName() |
Creates a unique name for an
uploaded BFILE. |
Can be abstract. See below. |
| prepareBfileSequenceQry() |
Creates a query used for
creating unique BFILE names. |
Will not exist if getArbitraryGeneratedBfileName() is
abstract. |
| Domain | Oracle or PL/SQL Data Type | Web
Services Data Type |
Comment | |||||||||||||||||||||||||
| Numeric | BINARY_INTEGER | All
numbers used by the service classes will be of the same data type. The
available types are: |
The data type is chosen in Step 4.4 of the user interface.l | |||||||||||||||||||||||||
| DEC | ||||||||||||||||||||||||||||
| DECIMAL | ||||||||||||||||||||||||||||
| DOUBLE PRECISION | ||||||||||||||||||||||||||||
| FLOAT | ||||||||||||||||||||||||||||
| INT | ||||||||||||||||||||||||||||
| INTEGER | ||||||||||||||||||||||||||||
| NATURAL | ||||||||||||||||||||||||||||
| NATURALN | ||||||||||||||||||||||||||||
| NUMBER | ||||||||||||||||||||||||||||
| NUMERIC | ||||||||||||||||||||||||||||
| PLS_INTEGER | ||||||||||||||||||||||||||||
| POSITIVE | ||||||||||||||||||||||||||||
| POSITIVEN | ||||||||||||||||||||||||||||
| REAL | ||||||||||||||||||||||||||||
| SIGNTYPE | ||||||||||||||||||||||||||||
| SMALLINT | ||||||||||||||||||||||||||||
| Text | CHAR |
String |
|
|||||||||||||||||||||||||
| CHARACTER | ||||||||||||||||||||||||||||
| LONG | ||||||||||||||||||||||||||||
| STRING | ||||||||||||||||||||||||||||
| VARCHAR | ||||||||||||||||||||||||||||
| VARCHAR2 | ||||||||||||||||||||||||||||
| Binary | LONG RAW |
byte[] |
|
|||||||||||||||||||||||||
| RAW | ||||||||||||||||||||||||||||
| ROWID |
String |
|
||||||||||||||||||||||||||
| UROWID |
String |
Not supported in JDBC as of 9.2.0 | ||||||||||||||||||||||||||
| Large Objects | BFILE |
byte[] |
Retrieval
works from Oracle 8.1.7 onwards. Creation of BLOBS and CLOBS works from Oracle 9.0.1 onwards. Note that the size of BLOBS, CLOBS and BFILES can easily exceed that which can be comfortably handled by a web server and that attention must be paid to JVM memory parameters. |
|||||||||||||||||||||||||
| BLOB | ||||||||||||||||||||||||||||
| CLOB | ||||||||||||||||||||||||||||
| Boolean | BOOLEAN |
boolean |
|
|||||||||||||||||||||||||
| Date | DATE |
java.util.date |
All | |||||||||||||||||||||||||
| TIMESTAMP |
String |
This value is a String
representation of an oracle.sql.TIMESTAMP data type. The format used is:yyyy-mm-dd hh:mm:ss.fffffffffAn oracle.sql.TIMESTAMP representing 9:26AM and 50.12346 seconds on the 31st Jan, 1997 would be stored as 1997-1-31 9:26:50.123456000 |
||||||||||||||||||||||||||
| TIMESTAMP WITH LOCAL TIME ZONE |
byte[11] |
'String' is not a safe way to
represent this object as the 'toString()' method does not return a
value that can be used to construct an identical copy. We therefore
turn it into a byte array, which is how Oracle represents it
internally. The byte representation can be used to reconstruct the
value by passing it to the constructor of oracle.sql.TIMESTAMPTZ. Oracle's documentation states that the byte array is structured as follows: The internal
data for this object is stored as a 11 byte array in the super class'
storage area. The bytes are arranged as follows:
Static methods are used for conversions. |
||||||||||||||||||||||||||
| TIMESTAMP WITH TIME ZONE |
byte[13] |
'String' is not a safe
way to represent this object as the 'toString()' method does not return
a value that can be used to construct an identical copy. We therefore
turn it into a byte array, which is how Oracle represents it
internally. The byte representation can be used to reconstruct the
value by passing it to the constructor of oracle.sql.TIMESTAMPLTZ.
Oracle's documentation states that the byte array is structured as
follows: The
internal data for this object is stored as a
eleven byte array. The bytes are arranged as follows:
The timezone information is stored as an offset in the RegionID format or in the HOUR/MINUTE format 100 is added to the century and decade fields so that negative values will be positive and positive values will be higher than negative values. 1 is added to the month, hour, minute, second fields for the java objects since they start of from 0. |
||||||||||||||||||||||||||
| INTERVAL
YEAR MONTH |
String |
An
interval of
two years and three months would be stored as:2-3 |
||||||||||||||||||||||||||
| INTERVAL
DAY SECOND |
String |
An
interval of two
days, three
hours and 2.99 seconds would be stored as:2 3:0:2.99 |
||||||||||||||||||||||||||
| Records | %ROWTYPE | A custom Java class is created for each one. | ||||||||||||||||||||||||||
| PL/SQL Package Records | ||||||||||||||||||||||||||||
| Oracle TYPE Objects | ||||||||||||||||||||||||||||
| CURSORS | Either a WSDLRowSet
or a custom class is created. |
Whether a WSDLRowSet or a dedicated class is created depends on how much information OrindaBuild has about the contents of the Cursor. Cursors which are defined in packages are more likely to have dedicated classes created to represent the |
Oracle's LOB data types are unsuitable for serialization because they are pointers to objects inside Oracle databases. OrindaBuild gets round this by generating source code that uses byte[] instead.
Generated code will create service methods that return byte arrays (byte[]) when the underlying PL/SQL procedure or SQL query returns a BLOB, CLOB or BFILE. If you are returning LOBS that are bigger than a few kilobytes in size you will need to make sure that the Java Virtual Machine the service is running on has been allocated a large amount of memory.
OrindaBuild uses Oracle's createTemporary() method when inserting LOBs using a service. 'createTemporary()' was introduced in V9.0.1 of Oracle. This means that OrindaBuild requires that you are using at least Oracle V9.0.1 if you wish to insert BLOBS and CLOBS using a Web Service.
Using a web service to create BFILEs requires that the Java Virtual Machine that is hosting the service has access to the same filesystem as the Oracle database and also that it has the ability to create files in the directories that database is using for storing BFILES. In order to create a BFILE you need to create the BFILE pointer object inside the database and then create a matching file in the location it refers to. This implies that you are on the same physical machine as the Oracle database server.
OrindaBuild web service code has been tested against the configurations below. OrindaBuild should work with the final version of Axis 1.2. Currently it fails with Axis 1.2.1 due to the blocker bugs AXIS-1985 and AXIS-1986
| Java
Virtual Machine |
Web
Server |
Web
Service Toolkit |
| Sun JDK 1.4.2 |
Apache Tomcat/4.1.31 | Apache Axis 1.1 |
| Sun JDK 1.5.0 | Apache Tomcat/4.1.31 | Apache Axis 1.2.1 (see AXIS-1985
and AXIS-1986) |
| Sun JDK 1.5.0 | Apache Tomcat/5.0.28 | Apache Axis 1.1 |
| Sun JDK 1.5.0 | Apache Tomcat/5.0.28 | Apache Axis 1.2.1 (see AXIS-1985 and AXIS-1986) |
| Sun JDK 1.5.0 | Apache Tomcat/5.5.4 | Apache Axis 1.1 |
| Sun JDK 1.5.0 | Apache Tomcat/5.5.4 | Apache Axis 1.2.1 (see AXIS-1985 and AXIS-1986) |