Oracle9i Servlet Engine Developer's Guide
Release 1 (9.0.1)

Part Number A90213-02
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

3
OSE Configuration and Examples

This chapter describes how to set up and configure applications to run in the Oracle Servlet Engine under the Oracle JVM. Also included are many examples that show the configuration steps, and some demo servlet applications.

Accessing servlets in the OSE/OJVM by going through the Oracle HTTP Server (powered by Apache) and the mod_ose module requires additional configuration steps. Chapter 5, "Configuring mod_ose" describes these steps.

This chapter contains the following topics:

Connecting to the OSE

The OSE runs in a virtual JVM inside an Oracle (database) server session. You must be running an Oracle shared server configuration to run the Oracle JVM, and hence to use the OSE. There are three ways that an HTTP client can access a servlet or JSP in the OSE:

  1. by connecting to an OSE Web service directly through a dispatcher

  2. by connecting to an Oracle listener that is configured to hand HTTP requests off to an OSE Web service (through a dispatcher)

  3. by connecting to the Oracle HTTP Server (powered by Apache), and routing HTTP client requests through mod_ose to the Oracle Servlet Engine in an Oracle (database) server

The first of these possibilities can be useful for debugging, or for quick testing of deployed servlets. But because it does not provide adequate scaling when multiple clients are involved, it should never be used when developing or testing production applications.

The second possibility can serve when your application consists solely of stateful servlets or JSPs. This, however, is true of few applications.

The third possibility is the one that Oracle recommends for all applications. Static HTML pages and other static data are served from the Oracle HTTP Server, and requests for dynamic content are routed through mod_ose to the OSE. To set up your application to run in this mode, there are additional configuration steps that you must perform. For example, you must configure the Apache mod_ose configuration file ose.conf to indicate which requests will be routed to the OSE. See Chapter 4, "An Apache Module for OSE" and Chapter 5, "Configuring mod_ose" for information about configuring mod_ose.

It is also possible to use the Oracle HTTP Server with mod_ose to connect to OSE applications with a server configuration that does not normally use shared servers. See "Non-Shared Server Installations" for more information.

Configuration Steps

Configuring the Oracle Servlet Engine itself and an application that is to run in the OSE requires some or all of the following steps:

  1. possible reconfiguration of the Oracle server, through the server startup file (the "INIT.ORA" file)

  2. establishment of Oracle Net parameters, for example by modifying the TNSNAMES.ORA file or an LDAP configuration file

  3. creating an OSE Web service that listens to one or more endpoints

  4. creating an OSE Web domain to contain the application contexts

  5. modifying the properties of a Web domain

  6. creating one or more application (servlet) contexts

  7. modifying the properties of an application context

  8. loading servlets (and JSPs) into the Oracle server (the database)

  9. publishing servlets so that the servlets have a virtual path associated with their location in the OSE namespace

Not all of these steps are required in all cases. For example, steps 1 through 7 will not be required to run most of the sample applications that come with this OSE release. You might need to perform steps 1 through 3 or 4 only once for all your application requirements.

Configuring the Oracle Server

The OSE/OJVM runs in a "virtual JVM" in the Oracle server. As with any other application that uses the OJVM, you must be running the Oracle shared server to use the OSE.


Note:

The Oracle shared server was called the Oracle multi-threaded server (MTS) prior to Oracle9i.  


The shared server is configured in the server initialization file (traditionally called INIT.ORA file). Entries such as

shared_servers=5 
dispatchers="(PROTOCOL=tcp)" 

are typically found to indicate that a shared server configuration, with associated dispatchers, is in effect for the instance.

Oracle Net Configuration

When you are using the Oracle HTTP Server (Apache) together with mod_ose to access the OSE, you might need to configure the TNSNAMES.ORA file. If this file contains an entry called inst1_http, you can use that Oracle Net entry for mod_ose. If it does not, you must configure a descriptor for mod_ose. See "Oracle Net and Oracle Listener Configuration".

Creating a Web Service

This section describes how to create a single-domain OSE Web service. Later sections describe how to configure a Web domain for the service, and how to create servlet contexts and publish servlets in the domain.

In order to access servlets in the OSE, you must have created a service to handle incoming HTTP requests, as well as a Web domain in which the servlets can run. The service runs in the Oracle server. An Oracle server can support more than one service. For example, you might configure an OSE to serve administrative HTTP requests from one service, and application servlet requests from separate service. You can set up the administrative service so that it has additional privileges not available to the normal application Web service.

Commands

There are two session shell commands that the SYS user must issue to create a Web service: createwebservice and addendpoint.

To remove an existing Web service, the SYS user issues the destroyservice session shell command. To remove an existing endpoint, use the rmendpoint command. See "Examples" to see how the two commands are used.

createwebservice

Issue the createwebservice command from the session shell. The syntax for this command is

createwebservice -root <location> [optional_parameters] <service_name> 

The parameters of the command are

<service_name>

Required parameter that specifies the name of the new service. Any JNDI identifier is legal.

-root

Required parameter that specifies the location in the JNDI namespace for the Web service's service root.

-ip

Optional parameter that creates a service that uses IP-based virtual hosting.

-virtual

Optional parameter that creates a service that uses name-based virtual hosting. This parameter can be combined with the -ip parameter.

-properties <prop_groups>

Optional parameter that specifies a list of property groups to use as the defaults for this service. Specify the name-value pairs in the same way as in the setgroup command. See the Oracle9i Java Tools Reference for information about setgroup.

addendpoint

The addendpoint command is used to specify the endpoints (port numbers) on which a service listens. The syntax for this command is

addendpoint -port <port_number> [optional_parameters] <service> <endpoint_name> 

The parameters of the addendpoint command are

-port

Required parameter that specifies the TPC port number on which the service listens.

<service>

Required parameter that specifies the name of the service, as used in the createwebservice command, that the endpoint will listen on for incoming requests.

<endpoint_name>

Required parameter. Specifies the name of the endpoint. Any JNDI identifier is a legal endpoint name. The endpoint name is used in the rmendpoint command.

-listener

Optional parameter. Specifies the address of the listener to add the endpoint to for this service. If not specified, the endpoint is added to the default listener.

-net8

Optional parameter. This parameter indicates that the endpoint is an Oracle Net endpoint. It is used to establish endpoints for Oracle Net TTC connections, for use by mod_ose.

-interface <int_spec>

Optional parameter. Specifies the IP address used to connect to this service. The default allows all IP addresses. The IP address specified is mapped to the service domain.

-register

register is an optional parameter that saves the endpoint information in a table in the database. This means that every time the server is started, the specified endpoint is established. This avoids having to reconfigure the INIT.ORA file.

-ssl

Specifies that this is to be an Secure Socket Layer connection.

-threads <min> <max>

The minimum and maximum number of threads for the endpoint. The minimum value is started upon listener initialization; the maximum value is used to deny any more incoming requests.

-timeout

The socket read timeout value in seconds. The amount of time that the Web server will allow you to block on the socket.

Examples

As always in this Guide, '%' indicates an operating system prompt, and '$' indicates a session shell prompt.

Here are examples of the commands that you can use to create a single-domain service named testService, and add named endpoints to it:

$ createwebservice -root /testRoot testService
#
$ addendpoint -port 8088 -register testService TestPublic
$ addendpoint -port 9088 -register -ssl testService TestSSL
$ addendpoint -net8 -register testService TestNet8

This example adds two dynamically-registered endpoints for connection through an Oracle listener, on ports 8088 and (for SSL) port 9088. The last endpoint is for access to OSE from Apache and mod_ose, which uses the normal Oracle Net TTC. If you always connect using mod_ose, as recommended by Oracle, you only need to use the last addendpoint command.

.


Important Warning:

When you create a new service, it is usually owned by SYS, because only SYS can add an endpoint to a new Web service.

For application services, it is very important to remove the SYS privileges from the newly-created service root.

Create Web domains in the service when connected to the session shell as the eventual real owner, not as SYS.

If you do not do these things, servlets that run under the new service and domain(s) inherit SYS privileges, and could browse and modify a database at will, possibly causing irreparable damage. 


The following session shell commands (issued as SYS) show how to make the HR schema the owner of his service:

$ cd
$ chown -R HR /testRoot

rmendpoint

Use this command to remove a previously established endpoint.

The syntax is:

rmendpoint [-force] <service> <name>

where the <service> is the name of the service that the endpoint was originally established for, and <name> is the endpoint name that was used in the addendpoint command.

If this command results in errors, or does not seem to remove the endpoint (shown by errors when trying to create a new endpoint of the same name on the same service), use the -force option. It never hurts to use -force.

After creating the service, you can examine the properties of the service using either the getproperties command, or more specifically the getgroup command, to examine the properties of the service group of the newly-created testService service. In the createwebservice example command above, notice that neither the name-based virtual-hosting (-virtual) nor IP-based virtual-hosting (-ip) options are specified. This means that neither service.http.virtual-host nor service.http.multi-homed properties are present in the service property group of the testService service. You can verify this by issuing the commands

$ cd /service
$ getgroup testService service

Changing Service Properties

You can change properties of the service using the addgroupentry session shell command, but you must be careful if you do this. Changing properties at random, without a real understanding of their function, can cause the service to malfunction or to stop working completely.

Some service properties that you might need to change are:

Creating Multi-Domain Web Services

See "Virtual-Hosted Services" for general information about multi-domain Web services. To create a multi-domain service, the SYS user issues the session shell command createwebservice, just as for a single-domain service. The difference is that either the -ip or the -virtual options are used. Both options are used to create a Web service that supports both IP-based and name-based virtual hosting.

Examples

Name-Based

Here is an example of session shell commands that create Web domains for a name-based virtual-hosted service:

$ createwebservice -root /vhost -virtual vhostService
$ addendpoint -port 8011 -register vhostService ep8011
$ createwebdomain -docroot /private/youruserID/test/docsv1 /vhost/xyz.com
$ createwebdomain -docroot /private/youruserID/test/docsv2 /vhost/xyz.us.com

Note that each Web domain under /vhost has the same name as a separate DNS domain name. Now the request URLs

http://xyz.com/

and

http://xyz.us.com/

will be served by different Web domains. One domain might be used for one of a company's product lines, the other Web domain to support a different part of the company.

IP-Based

Consider a system that has two network cards. The network interfaces are configured to the IP addresses 10.5.5.10 and 10.5.5.11.


Note:

IP addresses must be statically assigned for IP-based virtual hosting support to work. An IP-based virtual hosted Web service cannot work in a subnet where IP addresses are dynamically assigned. 


Configure an OSE to support these three network interfaces, each having a separate Web domain, using the following session shell commands:

$ createwebservice -ip -root /MHhost MHService

Note the properties that are established for the MHService:

$ cd /service
$ getproperties MHService
--group--=service
service.name=Service MHService
service.description=Aurora HTTP Servlet Engine
service.version=1.0
service.vendor=Oracle Corp.
service.globalTimeout=60
service.root=/MHhost
service.presentation=http://MHService
service.error.log=servicelogs/error
service.event.log=servicelogs/event
service.http.multi-homed=true
...

The last property in this abbreviated list is the one that determines that the Web service supports IP-based virtual hosting.

Now create the domains:

# the backslash is a line-continuation character
$ createwebdomain -docroot /private/youruserID/test/docs010.005.005.010 \
/MHHost/10.5.5.10 $ createwebdomain -docroot /private/youruserID/test/docs010.005.005.011 \
/MHHost/10.5.5.11

$

Creating Web Domains

Before creating one or more Web domains, first create the Web service that hosts the domains. See "Creating a Web Service" for instructions.

Creating a Single-Domain Web Domain

The single-domain Web domain has a name that is the same as its service root. For example, you created a single-domain service in the example above with the root /testRoot. To create a Web domain under this root, use the createwebdomain session shell command.

When you create a Web domain, you specify a document root, using the -docroot parameter. This is a place in the file system on the server's system from which the OSE serves static pages. For example, on a UNIX system create a directory such as /private/youruserID/test/docs. Put an HTML file, perhaps welcome.html, in that directory.

Files in the OS filesystem have access permissions that are associated with the operating system users, for example UNIX or Windows NT logins. But for the OSE to access files in the OS file system, the files must have Java file permissions for the database user who is trying to access the file.

You assign the files Java access permissions through SQL commands. The permissions are assigned to database users, not to OS logins. Use the grant_permission procedure in the dbms_java package to grant (or restrict) Java permissions (java.io.FilePermission) on files in the operating system.

See the Security chapter in the Oracle9i Java Developer's Guide for more information about Java file permissions.

Here is an example that creates a Web domain, using the session shell:

$ createwebdomain -docroot /private/youruserID/test/docs /testRoot

On a Windows NT or Windows 2000 system, create a directory such as C:\test\docs, and issue the create command as:

$ createwebdomain -docroot C:\test\docs /testRoot

To set the file permissions, use SQL*Plus. For example, to assign read and write permissions to the HR user for the doc_root /private/youruserID/test/docs (and all subdirectories of it) of the createwebdomain example above, enter SQL*Plus as the SYS user and issue the command:

SQL> call dbms_java.grant_permission('HR', 'java.io.FilePermission', 
'/private/youruserID/test/docs/*', 'read,write');

Once you have established the service, and a service endpoint, the OSE can always access this domain directly. For example, the URL

http://Oratest:8080/

will access the /testRoot domain as long as these conditions are met:

In this example, the hostname part of the URL is only used by the DNS servers. The OSE receives the complete URL, as well as the IP address, but does not need to process either to find the Web domain. There is only one Web domain established for that service.

Some machines have multiple entries (multiple host names) in the DNS namespace for the same IP address. For example, the hostnames Oratest and Oratest.us.oracle.com might map to the same address. (On UNIX-like systems, this can be seen in the /etc/hosts file.) Assume that the IP address in this case is 10.5.5.10. So, given the create service and create Web domain conditions above, each of the following URLs gets a request to the same OSE Web domain on the Oratest machine:

http://Oratest/
http://Oratest.us.oracle.com/
http://10.5.5.10/

(In this case, the default servlet for the testRoot service is activated by these URLs.)

Creating Servlet Contexts

Before creating a servlet context, you must establish a Web domain in which the context will exist. See "Creating Web Domains".

There are two ways to create and configure a servlet context for the OSE:

This chapter uses the session shell commands in examples, because they show finer-grained control of the servlet context. See Chapter 8, "Oracle WAR Deployment" for information about deploying an application using WAR files.

In the session shell, use the createcontext command to create a servlet context. The syntax of this command is:

createcontext -virtualpath <path> [options] <domain_name> <context_name>

where the options are

  [-recreate]
[-properties <prop_groups>]
[-docroot <location>]
[-stateless]

Here is an example that uses this command to create a servlet context named HRRoot in the /HRRoot Web domain:

$ createcontext -virtualpath /ose/hr -docroot /private/hr/test/html
/HRRoot HRContext

The command parameters and options are:

-virtualpath

This is a required parameter, not an option. Use it to specify a path in the URL that precedes the servlet path. See "Finding the Servlet" for more information about how the OSE processes the URL, and finds the right servlet context and servlet. The minimum virtualpath is '/'.

<domain_name>

The JNDI name of the Web domain that the context is to be located in. The domain name should be an absolute path. For example, a Web domain in a virtual hosted service (both IP- and name-based) might be /vhost/10.5.5.10/web1.

<context_name>

The name you give the servlet context. This name is arbitrary. It is used when you configure the context, publish servlets to the context, and when you finally destroy the context.

-docroot

Specify the location in the file system of the computer on which the OSE runs where static files (such as HTML files) are kept. The docroot must be specified as an absolute path.

-recreate

If a context with this name already exists, delete it before adding an empty context with this name. Doing this destroys any servlets that were associated with this context before the present createcontext command.

-properties

<prop_groups> List of property groups to use as the defaults for this service. Specify the name-value pairs in the same way as in the setgroup command.

-stateless

All servlets in this context are stateless. Contexts declared to be stateless can contain only servlets that are stateless. Stateless servlets never try to access the HTTPSession object.

Configuring a Servlet Context

When you create a servlet context, the root context has a config object. By default, this object has the property groups and property/value pairs shown below, for the HRContext that was created in the previous example:

$ cd /HRRoot/contexts/HRContext
$ getproperties config
--group--=context.properties
context.browse.dirs=true
context.welcome.names=index.html:index.htm
context.accept.charset=ISO-8859-1
context.accept.language=en
context.default.languages=*
context.default.charsets=*
--group--=context.params
--group--=context.mime
java=text/plain
html=text/html
htm=text/html
body=text/html
--group--=context.servlets
/errors/internal=internalError
--group--=context.error.uris
401=/system/errors/401.html
403=/system/errors/403.html
404=/system/errors/404.html
406=/system/errors/406.html
500=/errors/internal

You must configure the new context so that it has the properties that are appropriate for your application. Do this by using the accesslog and the addgroupentry session shell commands.

accesslog

This command specifies how HTTP access logging is handled for the servlet context. Access logging records information about each incoming HTTP request. The syntax for the accesslog command is:

accesslog [options] <context_name>
[-trace]
[-systable
[-table <table_spec>]

For more information about the required logging tables, see "Logging".

addgroupentry

Use this command to add or change the values for properties (in property groups) in the config file. The syntax for this session shell command is:

addgroupentry <object_name> <group_name> <property_name> <property_value>

The parameters for this command are:

<object_name>

The name of the target object to which properties are to be added, or whose properties are to be modified.

<group_name>

The name of the property group containing the property. For example, context.properties.

<property_name>

The name of the new or changed property.

<property_value>

The string or numeric entry for the property value.

\

You can add the following propertiesto the servlet context config object:

context.browse.dirs

If "true", allows the response to list the files in a directory, when the URL ends with a '/'.

context.debug

If "true", sends debug output to the console.

context.default.charsets

The charset(s) that are supported.

context.default.languages

The two-letter standard abbreviation for the languages that are supported. Following the HTTP specification.

context.default.timeout

The timeout for all servlets in the servlet context. The value is in seconds.

context.runAsOwner

Allows servlets in the servlet context to run with the permissions of the JNDI owner of the context, rather than inheriting the permissions of the web domain owner. See "Run As Owner" for more information on using this property.

Other config Property Groups

context.mime

The context.mime property group lists the MIME types supported by the context.

context.servlets

The context.servlets group contains the virtual path mappings for each published servlet in the context.

context.error.uris

The context.error.uris group shows the mappings for HTTP errors to HTML files, or other files that the OSE responds with when the error occurs.

Logging

The OSE logs events and errors. By default, logs are directed to the JAVA$HTTP$LOG$ table in the database, which is in the SYS schema. If your application requires that you process and have available the logs of events (HTTP requests, for example), and errors (and this is always a good idea), then you should redirect the event and errors to tables in the schema that owns the context.

These are the actions that you must take to enable per-context logging for your application:

System Classes

Use the session shell bind command to bind the event and error handling capability into the /servicelogs context of the service. Indicate the names of the tables that you created in the step above to set an attribute for the bound classes. Here are examples based on the HRService:

bind /HRRoot/servicelogs/event -rebind \
   -c SYS:oracle.aurora.namespace.rdbms.TableStream \
   -f oracle.aurora.namespace.PublishedObjectFactory \
   -string table.name HR.EVENT$LOG

bind /HRRoot/servicelogs/error -rebind \
   -c SYS:oracle.aurora.namespace.rdbms.TableStream \
   -f oracle.aurora.namespace.PublishedObjectFactory \
   -string table.name HR.ERROR$LOG

Logging Tables

The names used below are for the tables created for the HRRoot demos. You may use any names for your application. There are three tables:

The HTTP log table has the same structure as SYS.JAVA$HTTP$LOG$. Here is its description, as produced by SQL*Plus:

Column Name                    Type
------------------------------ ----
SERVER_NAME                    VARCHAR2(80)
TIMESTAMP                      DATE
REMOTE_HOST                    RAW(4)
REMOTE_USER                    VARCHAR2(80)
REQUEST_LINE                   VARCHAR2(256)
STATUS                         NUMBER(3)
RESPONSE_SIZE                  NUMBER(38)
REQUEST_METHOD                 RAW(1)
REFERER                        VARCHAR2(80)
AGENT                          VARCHAR2(80)

The description of the EVENT$LOG table is:

Column Name                    Type
------------------------------ ----
ID                             NUMBER
LINE                           NUMBER
TEXT                           VARCHAR2(4000)

And here is the ERROR$LOG table:

Column Name                    Type
------------------------------ ----
ID                             NUMBER
LINE                           NUMBER
TEXT                           VARCHAR2(4000)

You must also create sequence numbers for use by the event and error logging. The following SQL commands create the required sequences. These are for the HR schema, substitute your own schema name and sequence names, as required:

create sequence HR.EVENT$LOG_ID
create sequence HR.ERROR$LOG_ID

Oracle supplies example servlets that you can use or adopt to view the log tables. They are the HttpRdbmsLogServlet and the TableReaderServlet classes. You can use the following session shell commands to publish these servlets into your context. Use the table names that you employed in the CREATE TABLE commands to set the table.name property for the published names.

$ publishservlet -virtualpath /http_log HRContext httpLog_viewer \
SYS:oracle.aurora.mts.http.servlet.HttpRdbmsLogServlet -properties \
table.name=HR.HTTP$LOG$ $ $ publishservlet -virtualpath /error_log HRContext error_log_viewer \
SYS:oracle.aurora.mts.http.servlet.TableReaderServlet -properties \
table.name=HR.ERROR$LOG $ $ publishservlet -virtualpath /event_log HRContext event_log_viewer \
SYS:oracle.aurora.mts.http.servlet.TableReaderServlet -properties \
table.name=HR.EVENT$LOG

Timeouts

The timeout values determine how long a stateful session will stay active after the last request. There are two timeout properties for the service. In addition, each servlet context can establish its own timeout value, which takes precedence over the global service and endpoint timeouts. Also, individual servlets can set a timeout value for the session, using the setMaxInactiveInterval() method of the HttpSession interface.

Global Timeout

This is a property of the service group for the service. This value defaults to 60 seconds when a service is created. You can change the default using the createservice command when you create the service, but you cannot change it if using the createwebservice command.

You can see the value of the global timeout by entering these commands in the session shell:

$ cd /service
$ getgroup <service_name> service

You can also change the global timeout using the addgroupentry command, after the service has been 
created. Specify the new value in seconds. 
Endpoint timeout

Each service endpoint can have a separate timeout value, less than or equal to the global session service timeout. You can set the timeout for each endpoint when the endpoint is established, using the -timeout option of the addendpoint command (value in milliseconds). You can see the timeout values for all endpoints by using these session shell commands:

$ cd /service
$ getgroup <service_name> endpoint

Servlet Context Timeout

Each servlet context can have a default timeout, which applies to all servlets in the context that have not set their own timeout values. The servlet context default timeout is set in the config object of the servlet context. (The config object for the servlet context is in the root directory of the context.)

This timeout is set in the context.properties group of the config object, as the property context.default.timeout. Set it using the addgroupentry command, as follows (using the HR demo context as the example):

$ cd /HRRoot/contexts/HRContext
$ addgroupentry config context.properties context.default.timeout NN

where NN is the timeout value in seconds.

Publishing Servlets

Use the publishservlet session shell command to publish servlets. The syntax of this command is:

publishservlet [options] <context_name> <servlet_name> <class_name

where the options are:

    [-virtualpath <path>]
[-stateless]
[-reuse]
[-properties props]

The command parameters are:

<context_name>

The servlet context path into which to publish.

<servlet_name>

The name to be given to the servlet in the named_servlets directory of the servlet context.

<class_name>

The name of the class in the schema. This is the class that you loaded using the loadjava command, or a class that was loaded in a deployment file.

-virtualpath

The path name that will be used in the URL to reach the servlet

-stateless

The servlet is stateless. Stateful is the default property.

-reuse

Add the specified virtual path to an existing servlet without republishing the servlet. This could also be done by adding a property to the context.servlets property group in the servlet context config object.

-properties

<prop_groups> List of property groups to use as the defaults for this service. Specify the name-value pairs in the same way as in the setgroup command. See the Oracle9i Java Tools Reference for information about this command.

The publishservlet command does two things:

The JNDI object that is bound into the named_servlets directory contains the servlet class name and any initialization parameters for the servlet, as specified in the -properties option of the publishservlet command. You can see the class name and other properties of a published servlet by using the getproperties session shell command on the published object.

Summary

This section reviews and summarizes information that has been presented in previous sections. It presents a complete scenario, in which the following steps are performed:

Where it is useful, the results of a step are examined. For example, after many steps that use session shell commands, the ls and getproperties commands are used to examine the results of the step. SQL*Plus is also used to show the results when objects are added to the database. If you follow each step in this Summary, you should have a better understanding of how to use the Oracle Servlet Engine to develop servlet-based applications.

Throughout this section, as in the remainder of this guide, we use the following notational conventions:

Remember that each of the commands used is also documented in earlier sections of this chapter and in the Oracle9i Java Tools Reference.

Creating a Web Service

This step creates a Web service that supports a single Web domain. The service is called the testService, and is created to be used by the familiar schema HR.

Step 1a

To start off, enter the session shell as the SYS user:

% sess_sh -user SYS -password change_on_install -role SYSDBA -service \
http://localhost:8080


Notes:

The session shell must be on your command path. It is in $ORACLE_HOME/bin.

If localhost does not work in your environment, substitute the name of the host on which the OSE/OJVM is running.

Port 8080 is the default port for the OSE/OJVM admin service, which supports the session shell on the server side. 


Once in the session shell, list the contents of the root directory of the JNDI namespace:

$ ls /

In a newly installed Oracle platform, you should see something like this:

bin/          HRRoot/    system/
etc/          service/   test/

Some of these "directories" (or JNDI contexts) might be absent, depending on your installation. But the bin, etc, service and system entries must be there. HRRoot is the root of the HRService--a service and Web domain that supports the demonstration servlets that are installed with Oracle9i.


Oracle8i Users:

The HRService demos are not available in Oracle8i, Release 3. See the OTN Web page for more information. 


Step1b

Create the Web service:

$ createwebservice -root /testRoot testService

$ ls
bin/          service/     
etc/          system/       testRoot/     

Verify that the service object was created in the /service context:

$ ls /service
admin  testService   HRService

Yes, it's there. Now add one endpoint to the service:

$ addendpoint -port 8088 -register testService testEndPoint

Look at the testService object in the /service context. What does it contain?

$ getproperties /service/testService
--group--=service
service.name=Service testService
service.description=Aurora HTTP Servlet Engine
service.version=1.0
service.vendor=Oracle Corp.
service.globalTimeout=60
service.root=/testRoot
service.presentation=http://testService
service.error.log=servicelogs/error
service.event.log=servicelogs/event
--group--=endpoint
endpoint.class=SYS:oracle.aurora.mts.ServiceEndpoint
endpoint.name=testEndPoint
endpoint.testEndPoint.interface=*
endpoint.testEndPoint.port=8088
endpoint.testEndPoint.backlog=50
endpoint.testEndPoint.min.threads=3
endpoint.testEndPoint.max.threads=5
endpoint.testEndPoint.timeout=30000
--group--=environment
--group--=contexts
--group--=mime
java=text/plain
html=text/html
...

Most of the properties under the group service are default values for the createwebservice command. Likewise the properties in the group endpoint are defaults added by the addendpoint command. Only service name and the endpoint port number are not defaults.

It is important to now make the schema HR the owner of the objects in the service. Not doing so would open a big security hole in the server.

$ chown -R HR /testRoot

Verify the ownership:

$ ls -l /testRoot
Read      Write     Exec      Owner     Date Time      Type         Name
SYS       SYS       SYS       HR     Feb 24 12:02   Context      servicelogs

Note that SYS remains the owner of the service object:

$ ls -l /service/testService
Read      Write     Exec      Owner  Date Time      Type     Name
SYS       SYS       SYS       SYS    Feb 24 12:02   Service  service/testService

This is normal, and is fact is required. You now have a working Web service, that supports a single Web domain.

Creating a Web Domain

The Web domain is created in the testRoot service, and has that name. Because this is a single-domain Web service, the name of the Web domain is arbitrary. When you create a Web domain, you also specify the default document root for the domain. You specify a directory on a file system of the host machine. You can put a welcome.html file in there to be served as the default page for the domain. (The file names and locations are arbitrary--you do not have to imitate the ones shown here.)

Before creating the Web domain, have a look at the service root:

$ cd
$ ls testRoot
servicelogs/

Note that the only object there is the servicelogs context. This is created by the createwebservice command. Now reconnect to the session shell as the HR user, and create the Web domain. First exit from the session shell, then restart it as the HR user:

$ exit
%
% sess_sh -user HR -password hr -service http://localhost:8080

$ createwebdomain -docroot /tmp/testDomain /testRoot

Look again at the /testRoot context:

$ ls /testRoot
config         contexts/      logs/          servicelogs/   

The createwebdomain command created a contexts "context", a logs context, and a config object in the root of the Web domain. What does the config object contain? Look at it:

$ cd /testRoot
$ getproperties config
--group--=environment
--group--=contexts
--group--=mime
java=text/plain
html=text/html
htm=text/html
body=text/html
xml=application/xml
...
# (and so on)

Not too much of interest here yet. We will come back to this config object later.

Important: Set the Java Permissions on the Document Root

This is a very important step. For clients to access the files in the document root, you must set the Java permissions on these files so that users can access them.


Note::

Java IO file permissions are granted from the database, using SQL commands. They are not the same as operating system permissions or access rights, even though the files in the document root are static files in the OS filesystem. 


You must first connect to the database as a user who has permissions to grant Java file access permissions to the required users. In this example we connect as the SYS user, but you can use any database user who has the right grant capability.

% sqlplus 'SYS/change_on_install as SYSDBA'
SQL> call dbms_java.grant_permission('HR', 'java.io.FilePermission', 
'/tmp/testDomain/*', 'read,write');
SQL> Call completed.
SQL> exit

The OS directory does not have to exist when you grant these permissions. See the Security chapter of the Oracle9i Java Developer's Guide for more information about file permissions.

Load an HTML page into the document root, using OS commands. Here is an example welcome page that you can use:

<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Welcome to the Test Context</title>
</head>

<body>
<h1 align="center"><b>Welcome to the Test Context</b></h1>
<p>This page is located in the doc root of the <i>test</i> context</p>
<p>The servlet context testContext is located at <a href="/ose/">/ose</a>
</body>

</html>

Bind the Classes for Service Event and Error Logging

When you create a Web service, you should bind the classes that perform the event and error logging into the service. See "System Classes". Use these commands while connected to the session shell as SYS:

bind /testRoot/servicelogs/event -rebind \
   -c SYS:oracle.aurora.namespace.rdbms.TableStream \
   -f oracle.aurora.namespace.PublishedObjectFactory \
   -string table.name HR.EVENT$LOG

bind /testRoot/servicelogs/error -rebind \
   -c SYS:oracle.aurora.namespace.rdbms.TableStream \
   -f oracle.aurora.namespace.PublishedObjectFactory \
   -string table.name HR.ERROR$LOG

Creating a Servlet Context

Connect to the session shell as the HR user, if you are not already there:

% sess_sh -user HR -password hr -service http://localhost:8080
$ 
$ createcontext -virtualpath /ose -docroot /tmp/testDomain
/testRoot testContext

Creating a Servlet

This section contains the code for an example servlet that you can use. The servlet accesses the HR.EMPLOYEES table in the database, which is part of the HR sample schema.

The servlet code uses JDBC statements to query the database. Note that the server-side internal driver (KPRB driver) is used. See the Oracle9i JDBC Developer's Guide and Reference for more information about this driver.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import oracle.jdbc.*;

public class simpleHRServlet extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
       throws ServletException, IOException
    {
      PrintWriter out = new PrintWriter(resp.getOutputStream());
      Connection conn = null;

      try {
        // connect with the server-side internal driver
        OracleDriver ora = new OracleDriver();
        conn = ora.defaultConnection();

        if (conn != null) {
          Statement stmt = conn.createStatement();
         ResultSet rset = stmt.executeQuery("select EMPLOYEE_ID, LAST_NAME, HIRE_DATE from
HR.EMPLOYEES order by HIRE_DATE"); resp.setContentType("text/html"); out.println("<html><head><title>Servlet JDBC Example</title></head><body>"); out.println("<table border=3 cellspacing=2 cellpadding=4 bgcolor=#FFFFE7>"); out.println("<tr><td>Employee Number<td>Last Name<td>Date Hired"); int counter = 0; while (rset.next()) { out.println("<tr><td>" + rset.getInt(1) + "<td>" + rset.getString(2) + "<td>" +
rset.getDate(3)); counter++; } out.println("</table><br>"); out.println("A total of "+ counter + " records"); out.println("</body></html>"); rset.close(); stmt.close(); conn.close(); } } catch (java.sql.SQLException e) { e.printStackTrace(out); } out.flush(); out.close(); } public void init(ServletConfig cfg) throws ServletException { super.init(cfg); } public void destroy() { super.destroy(); } public String getServletInfo() { return "A simple JDBC servlet"; } }

Compiling the Servlet

Use a Java compiler compliant with JDK 1.2 to compile the source on the client. Make sure that servlet.jar, dt.jar, tools.jar, and Oracle's classes12.zip are all on the classpath when you compile. Here is a Solaris example, but you might need to modify this for your Oracle installation:

% javac -g -classpath .:$ORACLE_HOME/lib/servlet.jar:$ORACLE_
HOME/jdbc/lib/classes12.zip:$ORACLE_
HOME/sqlj/lib/translator.zip:/usr/local/jdk1.2.2/lib/dt.jar:/usr/local/jdk1.2.2/
lib/tools.jar simpleHRServlet.java

Loading the Servlet into the Database

Use the loadjava command to load the compiled class simpleHRServlet.class into the database, as follows:

% loadjava -verbose -oracleresolver -resolve -oci8 -user HR \
-password hr simpleHRServlet.class

Publishing the Servlet

Use the session shell to publish the servlet to the OSE/OJVM, as follows:

% $ORACLE_HOME/bin/sess_sh -user HR/hr -service http://localhost:8080
-command "publishservlet -virtualpath /simpleServlet
/HRRoot/contexts/HRContext simpleHRServlet HR:simpleHRServlet"

Note that the virtual path /simpleServlet was assigned to the class simpleHRServlet in the command part of the session shell invocation.

Accessing the Servlet

We can now combine all the elements that we created in the previous sections to derive the complete URL that is needed to access the simpleHRservlet. They are shown in Figure 3-1:

Figure 3-1 Accessing the Servlet: the URL


Text description of URL_02.gif follows.
Text description of the illustration URL_02.gif

Use a Web browser to access the servlet, entering the URL shown in Figure 3-1.

Connection to the OSE

In the examples in this section, we have set up an endpoint for the Oracle listener, and the URL here assumes a direct connection to the Oracle listener and dispatcher. In your applications use Apache/mod_ose to access servlets. In that case, use the Apache listener port instead of 8088. If Apache is running, and mod_ose has been configured correctly, with a /ose/ Location directive, the rest of the URL can serve as is.

Adding Logging Tables

Each Web domain requires tables in the database that hold event and error logging information. Create these using SQL*Plus or another Oracle administrative tool. See "Logging" for more information.

-- The HTTP log table:
create table HR.HTTP$LOG$ (
       server_name VARCHAR2(80),
       timestamp DATE,
       remote_host RAW(4),
       remote_user VARCHAR2(80),
       request_line VARCHAR2(256),
       status NUMBER(3),
       response_size INTEGER,
       request_method RAW(1),
       referer VARCHAR2(80),
       agent VARCHAR2(80))
/

-- Here's where the event log is stored:
create table HR.EVENT$LOG ( id number, line number, text varchar2(4000) )
/
-- The event logging sequence:
create sequence HR.EVENT$LOG_ID
/
-- Here's where we store the error log
create table HR.ERROR$LOG ( id number, line number, text varchar2(4000) )
/
-- The sequence for controlling ordering in the error log table
create sequence HR.ERROR$LOG_ID
/
-- don't forget to commit, if auto commit is not on
commit;

Execute these statements using SQL*Plus or an Oracle database management tool.

Adding Security

In the simple example in this Summary section, we have said little about security. We did make sure that the JNDI objects published under the testService root were not owned by SYS, and we did make sure that the static HTML files under the doc root were accessible by at least the HR user.

But if you are using this simple scenario as a basis for a real Web application, you must make sure that you properly address client authentication and authorization issues. See Chapter 7, "Oracle Servlet Engine Security", in this guide. If you are using Oracle Single Sign-On, you should also refer to the documentation about mod_osso in "Using mod_osso with mod_ose".


Go to previous page Go to next page
Oracle
Copyright © 1996-2001, Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback