This chapter describes how to write Oracle XML DB applications in Java. It includes design guidelines for writing Java applications including servlets, and how to configure the Oracle XML DB servlets.
This chapter contains these topics:
You can use Java code in these ways:
In the database using the Java Virtual Machine (VM).
In a client or application server, using the OCI driver for JDBC.
Because Java runs in the database in the context of the database server process, the ways you can deploy and run Java code are restricted to the following:
You can run Java code as a stored procedure invoked from SQL or PL/SQL.
You can run a Java servlet.
Stored procedures are easier to integrate with SQL and PL/SQL code. They require Oracle Net Services as the protocol to access Oracle Database.
Servlets work better as the top-level entry point into Oracle Database, and require using HTTP(S) as the protocol to access Oracle Database.
When choosing an architecture for writing Java Oracle XML DB applications, consider the following guidelines:
If the downstream client wants to deal with XML in its textual representation, then using HTTP(S) to either access the Java servlets or directly access XMLType
resources performs the best, especially if the XML node tree is not being manipulated much by the Java program.
The Java implementation in the server can natively move data from the database to the network without converting character data through UCS-2 Unicode (which is required by Java strings). In many cases data is copied directly from the database buffer cache to the HTTP(S) connection. There is no need to convert data from the buffer cache into the SQL serialization format used by Oracle Net Services, then move it to the JDBC client, and then convert to XML. Loading on demand and the LRU cache for XMLType
are most effective inside the database server.
If the downstream client is an application that programmatically accesses many or most of the elements of an XMLType
instance using Java, then use JDBC XMLType
support for best performance. It is often easier to debug Java programs outside of the database server, as well.
Oracle XML DB servlets are intended for writing HTTP stored procedures in Java that can be accessed using HTTP(S). They are not intended as a platform for developing an entire Internet application. In that case, the application servlet should be deployed in Oracle Application Server application server and access data in the database either using JDBC, or by using the java.net.*
or similar APIs to get XML data through HTTP(S).
They are best used for applications that want to get into the database, manipulate the data, and write it out quickly as XML, not to format HTML pages for end-users.
Oracle XML DB provides a protocol server that supports FTP, HTTP 1.1, WebDAV, and Java Servlets. Oracle XML DB supports Java Servlet version 2.2, with the following exceptions:
The servlet WAR file (web.xml
) is not supported in its entirety. Some web.xml
configuration parameters must be handled manually. For example, creating roles must be done using the SQL CREATE ROLE
command.
RequestDispatcher
and associated methods are not supported.
Method HTTPServletRequest.getCookies()
is not supported.
Only one ServletContext
(and one web-app
) is currently supported.
Stateful servlets (and thus the HttpSession
class methods) are not supported. Servlets must maintain state in the database itself.
Oracle XML DB servlets are configured using the /xdbconfig.xml
file in Oracle XML DB Repository. Many of the XML elements in this file are the same as those defined by the Java Servlet 2.2 specification portion of Java 2 Enterprise Edition (J2EE), and have the same semantics. Table 32-1 lists the XML elements defined for the servlet deployment descriptor by the Java Servlet specification, along with extension elements supported by Oracle XML DB.
Table 32-1 XML Elements Defined for Servlet Deployment Descriptors
XML Element Name | Defined By | Supported? | Description | Comment |
---|---|---|---|---|
|
Java |
no |
Specifies an HTTP authentication method required for access |
-- |
|
Oracle |
yes |
Specifies an IANA character set name |
For example: ISO8859, UTF-8 |
|
Oracle |
yes |
Specifies a mapping between a filename extension and a charset |
-- |
|
Java |
no |
Specifies a parameter for a Web application |
Not yet supported |
|
Java |
yes |
A string for describing a servlet or Web application |
Supported for servlets |
|
Java |
yes |
A string to display with a servlet or Web application |
Supported for servlets |
|
Java |
no |
Indicates whether or not this servlet can function if all instances are not running in the same Java virtual machine |
All servlets running in Oracle Database MUST be distributable. |
|
Oracle |
yes |
Oracle error number |
|
|
Java |
yes |
HTTP(S) error code |
Defined by RFC 2616 |
|
Java |
yes |
Defines a URL to redirect to if an error is encountered. |
Can be specified through an HTTP(S) error, an uncaught Java exception, or through an uncaught Oracle error message |
|
Java |
yes |
Classname of a Java exception mapped to an error page |
-- |
|
Java |
yes |
A filename extension used to associate with MIME types, character sets, and so on. |
-- |
|
Oracle |
yes |
Oracle facility code for mapping error pages |
For example: ORA, PLS, and so on. |
|
Java |
no |
Error page for form login attempts |
Not yet supported |
|
Java |
no |
Config spec for form-based login |
Not yet supported |
|
Java |
no |
URL for the form-based login page |
Not yet supported |
|
Java |
Yes |
URL of icon to associate with a servlet |
Supported for servlets |
|
Java |
Yes |
Initialization parameter for a servlet |
-- |
|
Java |
No |
Java Server Page file to use for a servlet |
Not supported |
|
Oracle |
Yes |
IANA language name |
For example: en-US |
|
Oracle |
Yes |
Specifies a mapping between a filename extension and language content |
-- |
|
Java |
Yes |
Large sized icon for icon display |
-- |
|
Java |
Yes |
Specifies if a servlet is to be loaded on startup |
-- |
|
Java |
Yes |
Specifies the URL for an error page |
Can be a local path name or HTTP(S) URL |
|
Java |
No |
Specifies a method for authentication |
Not yet supported |
|
Java |
Yes |
Specifies a mapping between filename extension and the MIME type of the content |
-- |
|
Java |
Yes |
MIME type name for resource content |
For example: text/xml or application/octet-stream |
|
Oracle |
Yes |
Specifies an Oracle error to associate with an error page |
-- |
|
Java |
Yes |
Name of a parameter for a Servlet or |
Supported for servlets |
|
Java |
Yes |
Value of a parameter |
-- |
|
Java |
No |
HTTP(S) realm used for authentication |
Not yet supported |
|
Java |
Yes |
Specifies a role a particular user must have for accessing a servlet |
Refers to a database role name. Make sure to capitalize by default! |
|
Java |
Yes |
A servlet name for a role |
Just another name to call the database role. Used by the Servlet APIs |
|
Java |
No |
Defines a role for a servlet to use |
Not supported. You must manually create roles using the SQL |
|
Java |
Yes |
A reference between a servlet and a role |
-- |
|
Java |
Yes |
Configuration information for a servlet |
-- |
|
Java |
Yes |
Specifies the classname for the Java servlet |
-- |
|
Oracle |
Yes |
Specifies the programming language in which the servlet is written. |
Either Java, C, or PL/SQL. Currently, only Java is supported for customer-defined servlets. |
|
Java |
Yes |
Specifies a filename pattern with which to associate the servlet |
All of the mappings defined by Java are supported |
|
Java |
Yes |
String name for a servlet |
Used by servlet APIs |
|
Oracle |
Yes |
The Oracle Schema in which the Java class is loaded. If not specified, then the schema is searched using the default resolver specification. |
If this is not specified, then the servlet must be loaded into the |
|
Java |
No |
Configuration information for an |
|
|
Java |
No |
Timeout for an HTTP(S) session |
|
|
Java |
Yes |
Small icon to associate with a servlet |
-- |
|
Java |
No |
JSP tag library |
JSPs currently not supported |
|
Java |
No |
URI for JSP tag library description file relative to file |
JSPs currently not supported |
|
Java |
No |
Path name relative to the root of the Web application where the tag library is stored |
JSPs currently not supported |
|
Java |
Yes |
URL pattern to associate with a servlet |
See Section 10 of Java Servlet 2.2 spec |
|
Java |
No |
Configuration for a Web application |
Only one Web application is currently supported |
|
Java |
Yes |
Specifies a welcome-file name |
-- |
|
Java |
Yes |
Defines a list of files to display when a folder is referenced through an HTTP |
Example: |
Note:
The following parameters defined for the web.xml
file by Java are usable only by J2EE-compliant Enterprise Java Bean containers, and are not required for Java Servlet containers that do not support a full J2EE environment: env-entry
, env-entry-name
, env-entry-value
, env-entry-type
, ejb-ref
, ejb-ref-type
, home
, remote
, ejb-link
, resource-ref
, res-ref-name
, res-type, res-auth
.
The following elements are used to define access control for resources: security-constraint
, web-resource-collection
, web-resource-name
, http-method
, user-data-constraint
, transport-guarantee
, auth-constrain
. Oracle XML DB provides this functionality through access control lists (ACLs). An ACL is a list of access control entries (ACEs) that determines which principals have access to a given resource or resources. A future release will support using a web.xml
file to generate ACLs.
See Also:
Chapter 34, "Administering Oracle XML DB" for more information about configuring the/xdbconfig.xml
fileOracle XML DB handles an HTTP request using the following steps:
If a connection has not yet been established, then Oracle Listener hands the connection to a shared server dispatcher.
When a new HTTP request arrives, the dispatcher wakes up a shared server.
The HTTP headers are parsed into appropriate structures.
The shared server attempts to allocate a database session from the Oracle XML DB session pool, if available, but otherwise creates a new session.
A new database call and a new database transaction are started.
If HTTP(S) has included authentication headers, then the session is authenticated as that database user (just as if the user logged into SQL*Plus). If no authentication information is included, and the request is GET
or HEAD
, then Oracle XML DB attempts to authenticate the session as the ANONYMOUS
user. If that database user account is locked, then no unauthenticated access is allowed.
The URL in the HTTP request is matched against the servlets in the xdbconfig.xml
file, as specified by the Java Servlet 2.2 specification.
The Oracle XML DB Servlet container is invoked in the Java VM inside Oracle. If the specified servlet has not been initialized yet, then the servlet is initialized.
The Servlet reads input from the ServletInputStream
, and writes output to the ServletOutputStream
, and returns from method service()
.
If no uncaught Oracle error occurred, then the session is put back into the session pool.
Oracle Database uses one Java VM for each database session. A session that is reused from the session pool retains any state that is left over in the Java VM (Java static variables) from the last time that session was used.
This can be useful in caching Java state that is not user-specific, such as metadata, but Do not store secure user data in Java static memory. This could turn into a security hole inadvertently introduced by your application if you are not careful.
Node class DOM
has an Oracle-specific method called write()
, which takes the following arguments, returning void:
java.io.OutputStream
stream: A Java stream for writing the XML text.
String charEncoding
: The character encoding for writing the XML text. If NULL
, then the database character set is used.
Short
indent
The number of characters to indent nested XML elements.
Java method write()
has a shortcut implementation if the stream provided is the ServletOutputStream
provided inside the database. The contents of the Node are written in XML in native code directly to the output socket. This bypasses any conversions into and out of Java objects or Unicode (required for Java strings) and provides very high performance.
The APIs supported by Oracle XML DB servlets are defined by the Java Servlet 2.2 specification, the Javadoc
for which is available, as of the time of writing this, online at: http://java.sun.com/products/servlet/2.2/javadoc/index.html
Table 32-2 lists Java Servlet 2.2 methods that are not implemented. They result in run-time exceptions.
Example 32-1 shows a simple servlet that prints the content of file resource /public/test/foo1.text
.
Example 32-1 An Oracle XML DB Servlet
import javax.servlet.http.*; import javax.servlet.*; import java.util.*; import java.io.*; import java.util.*; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.sql.DriverManager; import java.sql.SQLException; import oracle.jdbc.OracleConnection; import oracle.jdbc.OracleDriver; import oracle.jdbc.OraclePreparedStatement; import oracle.jdbc.OracleResultSet; import oracle.sql.CLOB; import oracle.xdb.XMLType; import oracle.xdb.spi.XDBResource; public class test extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { try { // Get the database connection for the current HTTP session DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); OracleDriver ora = new OracleDriver(); OracleConnection databaseConnection = (OracleConnection) ora.defaultConnection(); String statementText = "SELECT XDBURIType('/public/test/foo1.txt').getClob() FROM DUAL"; OraclePreparedStatement statement = (OraclePreparedStatement) databaseConnection.prepareStatement(statementText); OracleResultSet resultSet = null; CLOB content = null; // Execute the statement resultSet = (OracleResultSet) statement.executeQuery(); while (resultSet.next()) {// The statement returns a CLOB. // Copy content of CLOB to server's output stream. content = resultSet.getCLOB(1); Reader reader = content.getCharacterStream(); Writer writer = new OutputStreamWriter(response.getOutputStream()); int bytesSent = 0; int n; char[] buffer = new char[CLOB.MAX_CHUNK_SIZE]; while (-1 != (n = reader.read(buffer))) { bytesSent = bytesSent + n; writer.write(buffer, 0, n); } writer.flush(); if (content.isOpen()) { content.close(); }} resultSet.close(); statement.close(); databaseConnection.close(); response.getOutputStream().write('\n'); } catch (SQLException sql) { throw new ServletException(sql); }} catch (ServletException se ) { se.printStackTrace(); } finally { System.out.flush(); }}}
To install the servlet, you compile it, then load it into Oracle Database:
% loadjava –grant public –u quine/curry –r test.class
Finally, register and map the servlet, associating it with a URL, as shown in Example 32-2.