This is an experimental Java servlet implementation of PL/SQL gateway functionality. This code is provided primarily for education and for use at your own risk.
To run this code, you must first have installed the Oracle OWA itself in your target database, and you must have installed a servlet execution environment (such as TomCat). If you plan to run under Apache, you will need to have the Jserv module installed.
The code was built and tested with JDK 1.3.1 and the TomCat servlet runner running under Apache. It was built using the Oracle 8.1.6 JDBC drivers for Java 1.2 on NT, and also tested on Linux. It should also work with JDK 1.1.8 and other servlet runners (such as the runner that comes with mod_jserv), but I haven't tested these cases. If you plan make any change in the deployment environment, but especially a platform other than NT, a JDK 1.1.8 environment, or a different version of Oracle or the JDBC driver set, I would strongly recommend recompiling the classes.
The following classes are included:
To install this code, you need to place all of the .class files on the CLASSPATH of your servlet runner. You can simply copy the files to a directory that's already on the path, or zip up the files into a file (e.g. owaj.zip) and place this file on the CLASSPATH. On my system, I deploy the .class files directly in the target area, e.g. /tomcat/webapps/examples/WEB-INF/classes).
If you want to run any of the test packages, you can install the SQL scripts provided with mod_owa and then put the test file owajtest.htm in the root web page directory for your web server (e.g. /htdocs for Apache, /webpages/ROOT/ for TomCat).
Even if you don't want the test code, you will need one SQL object that is not (yet) part of the OWA. I've reproduced it here in case you just want to create it from SQL*Plus and ignore the test scripts:
create or replace type OWA_ARRAY as table of VARCHAR2(32767); /
That's pretty much it for the basic installation. You still need to do the following:
There are two main things you need to do to configure a servlet:
The mechanism for doing these things depends on your servlet runner. For TomCat, the servlet environment I used for development, the configuration is done in a file called web.xml, typically found under a directory called WEB-INF (for instance, the file /tomcat/webapps/examples/WEB-INF/web.xml) controls servlets that execute underneath "examples".
The Owa servlet is configured using standard servlet parameters. It understands the following:
Parameter | Example | Description | ||
database | localhost:1521:ORCL | Connection information in the form host:port:SID. This parameter is required, but defaults to localhost:1521:ORCL | ||
dbusername | scott | Database username. This parameter is required, and has no default. The servlet will issue an error message if this isn't set. | ||
dbpassword | tiger | Database password. This parameter is required, and has no default. The servlet will issue an error message if this isn't set. | ||
document_path | docs | URL prefix for document reads. | ||
document_proc | mypackage.readfile | Name of document download procedure. | ||
default_page | mypackage.showpage | Procedure to run for default page (when no script is present in the URL. | ||
pool_size | 10 | Number of connections to save in the connection pool. The default is 10, the maximum is 100. | ||
auth_mode | PACKAGE | Specifies the PL/SQL authorization mode. Valid values are OWA_INIT, OWA_CUSTOM, and PACKAGE. The default is no aut | ||
alternate_owa | MY_OWA | Optional name of a package that implements an alternative to the OWA. Changes the prefix used before INIT_CGI_ENV, GET_PAGE, and AUTHORIZE. | ||
dad_charset | iso-8859-1 | Specifies the character set to use for content transfers. The default is "iso-8859-1". The only other value supported at the moment is "utf-8". |
Here's an example of the relevant portion of a web.xml file for TomCat:
<servlet> <servlet-name>owa</servlet-name> <servlet-class>Owa</servlet-class> <init-param> <param-name>database</param-name> <param-value>localhost:1521:ORCL</param-value> </init-param> <init-param> <param-name>dbusername</param-name> <param-value>scott</param-value> </init-param> <init-param> <param-name>dbpassword</param-name> <param-value>tiger</param-value> </init-param> <init-param> <param-name>dbpassword</param-name> <param-value>owa</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>owa</servlet-name> <url-pattern>/owa/*</url-pattern> </servlet-mapping>
Note particularly the mapping of the Owa class to a servlet short name ("owa"), and the mapping of the servlet short name to a URI pattern match ("/owa/*"). Also note the method for setting parameters as name/value pairs. If this appears in the web.xml file under /webapps/examples/WEB-INF/, this enables URLs of the form
http://localhost/examples/owa
to be directed into the Owa servlet.
The exact method of configuration will depend on your servlet execution environment.
In this discussion I'm assuming you're somewhat familiar with the operation of mod_owa, as described in modowa.htm.
The operation of the servlet is largely the same as mod_owa. The main difference (aside from functionality not yet implemented) is that you no longer have an Apache "Location" where the owa functionality is accessed. Instead, you have the Owa servlet itself as a virtual location. For example, on my system running TomCat's Jserv under Apache, the following path takes me to the Owa servlet:
http://localhost/examples/owa
Commands to the servlet then follow this in the URL in a manner identical to that for mod_owa, e.g.
http://mymachine/examples/owa/foobar?a=dog&b=cat
Most of the core functionality of mod_owa is there, though some of it may require changes to your PL/SQL code (described in the next section) because of limitations in the way the JDBC drivers handle collection arguments. There may be character-set issues, especially with file upload operations; I don't understand the Java binary/string conversion interfaces very well yet. This code hasn't been updated for almost a year, so at this time there are many mod_owa features that it doesn't implement.
The Owa servlet should work identically for the normal case of a procedure with named scalar argument bindings. However, there are issues with the positional argument mode, and PL/SQL code changes required for interfaces that involve PL/SQL table-of-string (collection) arguments. There are some other limitations as well, primarily with respect to the document upload/download interfaces. All of these are described below.
The biggest single problem with collections is that the JDBC drivers lack a means of binding them to PL/SQL table-of-string types, which are commonly used in both the OWA interfaces and in many user programs. It is possible to work around this problem by using the OWA_ARRAY type to pass the collections to PL/SQL, then transcribing the contents to a PL/SQL table of the appropriate type. In theory, the servlet could do this for any procedure call by simply generating the necessary transfer code as part of the anonymous block it builds to call the procedure. In fact it does exactly this to enable it to call the INIT_CGI_ENV and GET_PAGE functions.
Unfortunately the servlet can do that only if it knows the PL/SQL table type in advance, which it cannot know for user-written code. The suggested work-around is to add a "wrapper" procedure to the user package by overloading the interface name with a variant that accepts OWA_ARRAY arguments as inputs and contains the necessary transfer logic. For example, to call this procedure:
procedure TEST_ARRAY(N in number, A in VCTAB);
add this code to the package:
procedure TEST_ARRAY(N in number, A in OWA_ARRAY) is A_NEW VCTAB; begin for I in 1..N loop A_NEW(I) := A(I); end loop; TEST_ARRAY(N, A_NEW); end TEST_ARRAY;
Unfortunately, the standard servlet infrastructure for parsing GET query strings and POST parameters return a Java Hashtable object to the Owa servlet. This is unfortunate because the information about the exact order in which the arguments were encountered is effectively lost. It could be a serious problem for a call in positional mode, and it could affect procedures called in the flexible argument mode where there is an assumption about the argument order in the arrays.
The Owa servlet works around this problem by doing its own parse of the argument string and returning an ordered collection (a Vector). It then attempts to merge the unescaped argument values from the Hashtable. I believe it all works correctly but haven't exhaustively tested it.
NCHAR-based LOBs don't seem to be supported in the JDBC, so I was unable to generate a valid binding. Thus, besides the change to OWA_ARRAY types for the collections, the file read and write interfaces have one fewer argument under this servlet.
Because BFILEs follow NCLOBs in the argument order for mod_owa, I didn't bother implementing BFILE support, either.
Finally, because the foregoing omissions now mean that the only two LOB types supported by the servlet are the BLOB and the CLOB, I didn't bother adding a parameter to support variation in the LOB calling mode for document uploads and downloads; the servlet always calls with both the BLOB and CLOB handles, expecting one of these to be non-null on return.
I did not bother to implement the legacy LONG and LONG RAW file operations, because the JDBC doesn't seem to have streaming support for them.
This is implemented, but to keep the code simple I didn't bother allowing you to set both PACKAGE and one of OWA_INIT/OWA_CUSTOM. I reasoned that this was unlikely to matter to most users, since when PACKAGE is specified for mod_owa, the only use for OWA_INIT/OWA_CUSTOM is when a bare procedure is being called. In this situation the servlet uses the newer OWA_CUSTOM. If this matters to you, be sure you have the most recent OWA, or create a synonym from OWA_CUSTOM to OWA_INIT.
The implementation is incomplete versus the spec from mod_owa. The servlet will use the package name you specify as a replacement for the calls to INIT_CGI_ENV, GET_PAGE, and AUTHORIZE (when PACKAGE is not specified). However, if the OWA is overridden, the servlet version runs exclusively a mode that is the equivalent setting KEEPSTATE and WITHRAW, the call appearing as follows:
begin <package_name>.GET_PAGE(:cbuffer, :rbuffer, :moredata); end;
It doesn't yet support the normal GET_PAGE mode, nor does it support the LOB-based content return interface (USELOBS). It also doesn't give you control over the suppression of RESET_PACKAGE; if you override the default OWA, the servlet will always omit the call to RESET_PACKAGE.
None of this is supported by the servlet implementation.
None of the describe modes are supported because there's no OCIDescribeAny() in the JDBC interfaces.
These aren't supported, but would be easy (and important) to add.
These haven't been implemented, but would be easy to add. Also, the forced replacement procedure (OwaProc) isn't supported, but could be.
These can be implemented only with the release of the Oracle 9i JDBC drivers, which add support for NCHAR/NVARCHAR bindings.
None of the Basic authentication support is available, nor are the OAS-compatible settings. The ability to use native database logins is also not supported. All of this could be added (with considerable effort).
This hasn't been implemented yet.
These features were added to mod_owa for Oracle 9i and haven't been implemented yet.