| Oracle9i Support for JavaServer Pages Reference Release 2 (9.2) Part Number A96657-01 | 
 | 
Oracle9i release 2 includes an Apache JServ servlet environment. For those who use this environment, there are special considerations relating to servlet and JSP usage, as with any servlet 2.0 environment.
The following topics are covered here:
This section provides information about configuring JServ to run JSP pages, covering the following topics:
This section summarizes JAR and ZIP files required in order to use the Oracle JSP container, as well as optional JAR and ZIP files to use Oracle JDBC and SQLJ functionality, JML or SQL custom tags, or custom data-access JavaBeans.
Required files must also be added to your classpath. (See "Adding Files to the JServ Web Server Classpath".)
The following files are provided with Oracle9i release 2 and must be installed on your system:
ojsp.jar (the Oracle JSP container)xmlparserv2.jar (for XML parsing--required for the web.xml deployment descriptor in a servlet 2.2 environment, and for any tag library descriptors)servlet.jar (standard servlet library, servlet 2.2 version)In addition, if your JSP pages will use Oracle JSP Markup Language (JML) tags, SQL tags, or data-access JavaBeans, you will need the following files:
ojsputil.jar (Oracle JSP utility library)xsu12.jar, for JDK 1.2.x, or xsu111.jar, for JDK 1.1.x (for XML functionality)To run in a client environment, xsu12.jar or xsu111.jar is required only if you will use XML functionality in the data-access JavaBeans (such as getting a result set as an XML string). The xsu12.jar and xsu111.jar files are included with Oracle9i.
For Oracle data access, you will also need the following:
See "Files for JDBC (optional)" and "Files for SQLJ (optional)" for more information.
To use JDBC data sources or Enterprise JavaBeans, you will need the following:
(This file is required for some of the Oracle JSP demos.)
Note that Oracle JSP 1.1.x.x releases require and supply the 2.2 version of the servlet library, which is where the standard javax.servlet.* packages are located. Your Web server environment likely requires and supplies a different servlet library version. You must be careful in your classpath to have the version for your Web server precede the version for the Oracle JSP container. "Adding Files to the JServ Web Server Classpath" further discusses this.
Table 9-1 summarizes the servlet library versions. Do not confuse the Sun Microsystems JSWDK (JavaServer Web Developer's Kit) with the Sun Microsystems JSDK (Java Servlet Developer's Kit).
| Servlet Library Version | Library File Name | Provided with: | 
|---|---|---|
| servlet 2.2 | 
 | Oracle JSP, Tomcat 3.1 | 
| servlet 2.1 | 
 | Sun JSWDK 1.0 | 
| servlet 2.0 | 
 | Sun JSDK 2.0; also used with JServ | 
(For JServ, download jsdk.jar separately.)
The following files are required if you will use Oracle JDBC for data access. (Be aware that Oracle SQLJ uses Oracle JDBC.)
or:
or:
The following files are necessary if your JSP pages use Oracle SQLJ for their data access:
as well as the appropriate SQLJ runtime:
or:
or:
or:
or:
runtime-nonoracle.jar or .zip (generic--for use with non-Oracle JDBC drivers and any JDK environment)(The JDK 1.2.x enterprise edition allows data source support, in compliance with the ISO SQLJ specification.)
To add files to the Web server classpath in a JServ environment, insert appropriate wrapper.classpath commands into the jserv.properties file in the JServ conf directory. Note that jsdk.jar should already be in the classpath. This file is from the Sun Microsystems JSDK 2.0 and provides servlet 2.0 versions of the javax.servlet.* packages that are required by JServ. Additionally, files for your JDK environment should already be in the classpath.
The following example (which happens to use UNIX directory paths) includes files for JSP, JDBC, and SQLJ. Replace [Oracle_Home] with your Oracle Home path.
# servlet 2.0 APIs (required by JServ, from Sun JSDK 2.0): wrapper.classpath=jsdk2.0/lib/jsdk.jar # # servlet 2.2 APIs (required and provided by OC4J): wrapper.classpath=[Oracle_Home]/ojsp/lib/servlet.jar # JSP packages: wrapper.classpath=[Oracle_Home]/ojsp/lib/ojsp.jar wrapper.classpath=[Oracle_Home]/ojsp/lib/ojsputil.jar # XML parser (used for servlet 2.2 web deployment descriptor): wrapper.classpath=[Oracle_Home]/ojsp/lib/xmlparserv2.jar # JDBC libraries for Oracle database access (JDK 1.2.x environment): wrapper.classpath=[Oracle_Home]/ojsp/lib/classes12.zip # SQLJ translator (optional): wrapper.classpath=[Oracle_Home]/ojsp/lib/translator.zip # SQLJ runtime (optional) (for JDK 1.2.x enterprise edition): wrapper.classpath=[Oracle_Home]/ojsp/lib/runtime12.zip
Now consider an example where you have the following useBean command:
<jsp:useBean id="queryBean" class="mybeans.JDBCQueryBean" scope="session" />
You can add the following wrapper.classpath command to the jserv.properties file. (This example happens to be for a Windows NT environment.)
wrapper.classpath=D:\Apache\Apache1.3.9\beans\
And then JDBCQueryBean.class should be located as follows:
D:\Apache\Apache1.3.9\beans\mybeans\JDBCQueryBean.class
In a JServ environment, mapping each JSP file name extension to oracle.jsp.JspServlet--the JSP front-end servlet for JServ--requires an ApJServAction command in either the jserv.conf file or the mod_jserv.conf file. These configuration files are in the JServ conf directory.
(In older versions, you must instead update the httpd.conf file in the Apache conf directory. In newer versions, the jserv.conf or mod_jserv.conf file is "included" into httpd.conf during execution--look at the httpd.conf file to see which one it includes.)
Following is an example (which happens to use UNIX syntax):
# Map file name extensions (.sqljsp and .SQLJSP are optional). ApJServAction .jsp /servlets/oracle.jsp.JspServlet ApJServAction .JSP /servlets/oracle.jsp.JspServlet ApJServAction .sqljsp /servlets/oracle.jsp.JspServlet ApJServAction .SQLJSP /servlets/oracle.jsp.JspServlet
The path you use in this command for oracle.jsp.JspServlet is not a literal directory path in the file system. The path to specify depends on your JServ servlet configuration--how the servlet zone is mounted, the name of the zone properties file, and the file system directory that is specified as the repository for the servlet. ("Servlet zone" is a JServ term that is similar conceptually to "servlet context".) Consult your JServ documentation for more information.
This section describes the configuration parameters supported by the Oracle JspServlet.
Table 9-2 summarizes the configuration parameters supported by Oracle JspServlet, the front-end of the Oracle JSP container. For each parameter, the table notes the following:
ojspc translation options for pages you are pretranslating 
(The ojspc utility does not use JspServlet.)
Be aware of the following:
debug_mode and send_error are new with Oracle JSP 1.1.2.x releases.alias_translation is for use in the JServ environment only.session_sharing is for use with globals.jsa only (presumably in a servlet 2.0 environment such as JServ). 
| Notes: 
 | 
This section describes the Oracle JSP configuration parameters in more detail.
(boolean; default: false) (Apache-specific)
This parameter allows the Oracle JSP container to work around limitations in the way JServ handles directory aliasing. For information about the current limitations, see "Directory Alias Translation".
You must set alias_translation to true for httpd.conf directory aliasing commands, such as the following example, to work properly in the JServ servlet environment:
Alias /icons/ "/apache/apache139/icons/"
(boolean; default: false)
Normally, when a JSP page is requested, the Oracle JSP container will throw a FileNotFound exception if it cannot find the corresponding .jsp source file, even if it can find the page implementation class. (This is because, by default, the JSP container checks the page source to see if it has been modified since the page implementation class was generated.)
Set this parameter to true for the Oracle JSP container to proceed and execute the page implementation class even if it cannot find the page source.
If bypass_source is enabled, the JSP container will still check for retranslation if the source is available and is needed. One of the factors in determining whether it is needed is the setting of the developer_mode parameter.
| Notes: 
 | 
(fully qualified path; default: null)
Use this parameter to add classpath entries to the Oracle JSP default classpath for use during translation, compilation, or execution of JSP pages. For information about the Oracle JSP classpath and class loader, see "Classpath and Class Loader Issues".
The exact syntax depends on your Web server environment and operating system. See "Setting JSP Parameters in JServ" for some examples.
Overall, the Oracle JSP container loads classes from its own classpath (including entries from this classpath parameter), the system classpath, the Web server classpath, the page repository, and predefined locations relative to the root directory of the JSP application.
Be aware that classes loaded through the path specified in the classpath setting path are loaded by the JSP class loader, not the system class loader. During JSP execution, classes loaded by the JSP class loader cannot access (or be accessed by) classes loaded by the system class loader or any other class loader.
| Notes: 
 | 
(boolean; default: true)
Use the default true setting of this flag to direct the Oracle JSP container to print a stack trace whenever a runtime exception occurs. Set it to false to disable this feature.
(boolean; default: true)
Set this flag to false to instruct the Oracle JSP container to not routinely compare the timestamp of the page implementation class to the timestamp of the .jsp source file when a page is requested. With developer_mode set to true, the Oracle JSP container checks every time to see if the source has been modified since the page implementation class was generated. If that is the case, the JSP container retranslates the page. With developer_mode set to false, the JSP container will check only upon the initial request for the page or application. For subsequent requests, it will simply re-execute the generated page implementation class.
This flag also affects dynamic class reloading for JavaBeans and other support classes called by a JSP page. With developer_mode set to true, the Oracle JSP container checks to see if such classes have been modified since being loaded by the Oracle JSP class loader.
Oracle generally recommends setting developer_mode to false, particularly in a deployment environment where code is not likely to change and where performance is a significant issue.
Also see "Oracle JSP Runtime Page and Class Reloading".
(boolean; default: false)
Set this flag to true to instruct the Oracle JSP container to generate a line map to the original .jsp file for debugging during development. Otherwise, lines will be mapped to the generated page implementation class.
| Notes: 
 | 
(boolean; default: false)
Set this flag to true to instruct the Oracle JSP translator to place generated static content (the Java print commands that output static HTML code) into a Java resource file instead of into the service method of the generated page implementation class.
The resource file name is based on the JSP page name, with the .res suffix. With Oracle9i, translation of MyPage.jsp, for example, would create _MyPage.res in addition to normal output. The exact implementation may change in future releases, however.
The resource file is placed in the same directory as generated class files.
If there is a lot of static content in a page, this technique will speed translation and may speed execution of the page. In extreme cases, it may even prevent the service method from exceeding the 64K method size limit imposed by the Java VM. For more information, see "Workarounds for Large Static Content in JSP Pages".
(compiler executable; default: null)
This parameter is useful in any of the following circumstances:
javac command-line options (although default settings are typically sufficient)javac (optionally including command-line options)Specifying an alternative compiler results in the Oracle JSP container spawning that executable as a separate process in a separate JVM, instead of spawning the JDK default compiler within the same JVM in which the Oracle JSP container is running. You can fully specify the path for the executable, or specify only the executable and let the Oracle JSP container look for it in the system path.
Following is an example of a javaccmd setting to enable the javac -verbose option:
javaccmd=javac -verbose
The exact syntax depends on your servlet environment. See "Setting JSP Parameters in JServ".
| Notes: 
 | 
(fully qualified directory path; default: null)
The Oracle JSP container uses the Web server document repository to generate or load translated JSP pages. By default, in an on-demand translation scenario, the root directory is the Web server doc root directory (for JServ) or the servlet context root directory of the application the page belongs to. JSP page source is in the root directory or some subdirectory. Generated files are written to a _pages subdirectory or some corresponding subdirectory.
Set the page_repository_root option to instruct the Oracle JSP container to use a different root directory.
For information about file locations relative to the root directory and _pages subdirectory, see "Oracle JSP Translator Output File Locations".
| Notes: 
 | 
(boolean; default: false)
Set this flag to true to direct the Oracle JSP container to output generic "404" messages for file-not-found conditions, and generic "500" messages for compilation errors.
This is as opposed to outputting customized messages that provide more information (such as the name of the file not found). Some environments, such as JServ, do not allow output of a customized message if a "404" or "500" message is output.
(boolean; default: true) (for use with globals.jsa)
When a globals.jsa file is used for an application, presumably in a servlet 2.0 environment, each JSP page uses a distinct JSP session wrapper attached to the single overall servlet session object provided by the servlet container.
In this situation, the default true setting of the session_sharing parameter results in JSP session data being propagated to the underlying servlet session. This allows servlets in the application to access the session data of JSP pages in the application.
If session_sharing is false (which parallels standard behavior in most JSP implementations), JSP session data is not propagated to the servlet session. As a result, application servlets would not be able to access JSP session data.
This parameter is meaningless if globals.jsa is not used. For information about globals.jsa, see "Oracle JSP Application and Session Support for JServ".
(SQLJ translator executable and options; default: null)
This parameter is useful in any of the following circumstances:
(You can set multiple SQLJ options in the sqljcmd setting.)
Specifying a SQLJ translator executable results in the JSP container spawning that executable as a separate process in a separate JVM, instead of spawning the default SQLJ translator within the same JVM in which the JSP container is running.
You can fully specify the path for the executable, or specify only the executable and let the JSP container look for it in the system path.
Following is an example of a sqljcmd setting to log into scott/tiger for online semantics-checking and to generate ISO standard SQLJ code:
sqljcmd=sqlj -user=scott/tiger -codegen=iso
(The exact syntax depends on your servlet environment. See "Setting JSP Parameters in JServ".)
| Notes: 
 | 
(boolean; default: false)
| Note: Beginning with Oracle JSP 1.1.2.x releases, it is preferable to use the  | 
Set this flag to true to override servlet containers that do not encode multibyte (globalization support) request parameters or bean property settings. With this setting, the Oracle JSP container encodes request parameters and bean property settings. Otherwise, the JSP container returns the parameters from the servlet container unchanged.
For more information about the functionality and use of translate_params, including situations where it should not be used, see "Oracle JSP Extended Support for Multibyte Parameter Encoding".
(boolean; default: false) (for development only)
By default, the Oracle JSP container restarts the application and sessions whenever a JSP page is dynamically retranslated and reloaded (which occurs when the JSP translator finds a .jsp source file with a more recent timestamp than the corresponding page implementation class).
Set this parameter to true to instruct the JSP container not to restart the application after dynamic retranslations and reloads. This avoids having existing sessions become invalid.
For a given JSP page, this parameter has no effect after the initial request for the page if developer_mode is set to false (in which case the JSP container never retranslates after the initial request).
| Important: This parameter is intended for developers only and is not recommended for deployment environments. | 
Each Web application in a JServ environment has its own properties file, known as a zone properties file. In Apache terminology, a zone is essentially the same as a servlet context.
The name of the zone properties file depends on how you mount the zone. (See the JServ documentation for information about zones and mounting.)
To set JSP configuration parameters in a JServ environment, set the JspServlet initArgs property in the application zone properties file, as in the following example (which happens to use UNIX syntax):
servlet.oracle.jsp.JspServlet.initArgs=developer_mode=false, sqljcmd=sqlj -user=scott/tiger -codegen=iso,classpath=/mydir/myapp.jar
(This is a single wraparound line.)
The servlet path, servlet.oracle.jsp.JspServlet, also depends on how you mount the zone. It does not represent a literal directory path.
Be aware of the following:
initArgs commands are cumulative and overriding. For example, consider the following two commands (in order): 
servlet.oracle.jsp.JspServlet.initArgs=foo1=val1,foo2=val2 servlet.oracle.jsp.JspServlet.initArgs=foo1=val3
This combination is equivalent to the following single command:
servlet.oracle.jsp.JspServlet.initArgs=foo1=val3,foo2=val2
In the first two commands, the val3 value overrides the val1 value for foo1, but does not affect the foo2 setting.
initArgs parameters are comma-separated, there can be no commas within a parameter setting. Spaces and other special characters (such as "=" in this example) do not cause a problem, however.There are special considerations in running the Oracle JSP container in JServ-based platforms, because this is a servlet 2.0 environment. The servlet 2.0 specification lacked support for some significant features that are available in servlet 2.1 and 2.2 environments.
For information about how to configure a JServ environment for the Oracle JSP container, see the following sections:
This section discusses the following Apache-specific considerations:
JSP dynamic includes (the jsp:include action) and forwards (the jsp:forward action) rely on request dispatcher functionality that is present in servlet 2.1 and 2.2 environments but not in servlet 2.0 environments.
The Oracle JSP container, however, provides extended functionality to allow dynamic includes and forwards from one JSP page to another JSP page or to a static HTML file in JServ and other servlet 2.0 environments.
This Oracle JSP functionality for servlet 2.0 environments does not, however, allow dynamic forwards or includes to servlets. (Servlet execution is controlled by the JServ or other servlet container, not the JSP container.)
If you want to include or forward to a servlet in JServ, however, you can create a JSP page that acts as a wrapper for the servlet.
The following example shows a servlet, and a JSP page that acts as a wrapper for that servlet. In a JServ environment, you can effectively include or forward to the servlet by including or forwarding to the JSP wrapper page.
Presume that you want to include or forward to the following servlet:
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class TestServlet extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); System.out.println("initialized"); } public void destroy() { System.out.println("destroyed"); } public void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML><BODY>"); out.println("TestServlet Testing"); out.println("<H3>The local time is: "+ new java.util.Date()); out.println("</BODY></HTML>"); } }
You can create the following JSP wrapper (wrapper.jsp) for the preceding servlet.
<%-- wrapper.jsp--wraps TestServlet for JSP include/forward --%> <%@ page isThreadSafe="true" import="TestServlet" %> <%! TestServlet s=null; public void jspInit() { s=new TestServlet(); try { s.init(this.getServletConfig()); } catch (ServletException se) { s=null; } } public void jspDestroy() { s.destroy(); } %> <% s.service(request,response); %>
Including or forwarding to wrapper.jsp in a servlet 2.0 environment has the same effect as directly including or forwarding to TestServlet in a servlet 2.1 or 2.2 environment.
isThreadSafe to true or false in the wrapper JSP page depends on whether the original servlet is thread-safe.include or forward is to occur). You can use an instance of the standard java.net.URL class to create an HTTP request from the original JSP page to the servlet. (Note that you cannot share session data or security credentials in this scenario.) Alternatively, you can use the HTTPClient class from Innovation GmbH. The Oracle JVM provides a modified version of this class that supports SSL, directly or through a proxy, when you use https:// for the URL. (See http://www.innovation.ch/java/HTTPClient for general information about this class. Click "Getting Started" for information that includes how to replace the JDK HTTP client with the HTTPClient class.) Details of these alternatives are outside the scope of this document, however, and this approach is generally not recommended.The servlet 2.0 specification does not provide the full servlet context framework for application support that is provided in later specifications.
For servlet 2.0 environments, including JServ, the Oracle JSP container supplies its own application framework using a file, globals.jsa, that you can use as an application marker.
For more information, see "Distinct Applications and Sessions Through globals.jsa".
To share HTTP session information between JSP pages and servlets in a JServ environment, you must configure your environment so that oracle.jsp.JspServlet (the servlet that acts as the front-end of the Oracle JSP container) is in the same zone as the servlet or servlets with which you want your JSP pages to share a session. Consult your Apache documentation for more information.
To verify proper zone setup, some browsers allow you to enable a warning for cookies. In an Apache environment, the cookie name includes the zone name.
Additionally, for applications that use a globals.jsa file, the JSP configuration parameter session_sharing should be set to true (the default) for JSP session data to be accessible to servlets. See these sections for related information:
Apache supports directory aliasing by allowing you to create a "virtual directory" through an Alias command in the httpd.conf configuration file. This allows Web documents to be placed outside the default doc root directory.
Consider the following sample httpd.conf entry:
Alias /icons/ "/apache/apache139/icons/"
This command should result in icons being usable as an alias for the /apache/apache139/icons/ path. In this way, for example, the file /apache/apache139/icons/art.gif, could be accessed by the following URL:
http://host[:port]/icons/art.gif
Currently, however, this functionality does not work properly for servlets and JSP pages, because the JServ getRealPath() method returns an incorrect value when processing a file under an alias directory.
Oracle provides an Apache-specific JSP configuration parameter, alias_translation, that works around this limitation when you set alias_translation to true (the default setting is false).
Be aware that setting alias_translation=true also results in the alias directory becoming the application root. Therefore, in a dynamic include or forward command where the target file name starts with "/", the expected target file location will be relative to the alias directory.
Consider the following example, which results in all JSP and HTML files under /private/foo being effectively under the application /mytest:
Alias /mytest/ "/private/foo/"
Also assume there is a JSP page located as follows:
/private/foo/xxx.jsp
The following dynamic include command will work, because xxx.jsp is directly below the aliased directory, /private/foo, which is effectively the application root:
<jsp:include page="/xxx.jsp" flush="true" />
JSP pages in other applications or in the general doc root cannot forward to or include JSP pages or HTML files under the /mytest application. It is only possible to forward to or include pages or HTML files within the same application (per the servlet 2.2 specification).
| Notes: 
 | 
Also be aware that there are issues when two aliases begin with the same partial directory path. Consider the following two aliases as an example:
Alias /foo/bar1 "/path/to/my/dir/x/bar1" Alias /foo/bar2 "/path/to/my/dir/y/bar2"
An initial request for /foo/bar1/bar1.jsp will work, but a subsequent request for /foo/bar2/bar2.jsp will incorrectly look in /path/to/my/dir/x for bar2.jsp, and will fail with a FileNotFound exception. This is due to further limitations with the JServ getRealPath() implementation, which returns incorrect information. There are two workarounds for this situation:
Alias /foo "/path/to/my/dir"
Here the bar1 and bar2 directories would physically exist as /path/to/my/dir/bar1 and /path/to/my/dir/bar2, and there would not be a problem.
or:
Alias /foo/bar1 "/path/to/my/dir/x_bar1" Alias /foo/bar2 "/path/to/my/dir/y_bar2"
Note that the physical directories do not have the same name as the alias directories (unlike the problematic example above, where alias directories and physical directories shared bar1 and bar2 in common).
The Oracle JSP container defines a file, globals.jsa, as a mechanism for implementing the JSP specification in a servlet 2.0 environment. Web applications and servlet contexts were not fully defined in the servlet 2.0 specification.
This section discusses the globals.jsa mechanism and covers the following topics:
For sample applications, see "Samples Using globals.jsa for Servlet 2.0 Environments".
Within any single Java virtual machine, you can use a globals.jsa file for each application (or, equivalently, for each servlet context). This file supports the concept of Web applications in the following areas:
The globals.jsa file also provides a vehicle for global Java declarations and JSP directives across all JSP pages of an application.
To deploy an Oracle JSP application that does not incorporate servlets, copy the directory structure into the Web server and create a file called globals.jsa to place at the application root directory.
The globals.jsa file can be of zero size. The Oracle JSP container will locate it, and its presence in a directory defines that directory (as mapped from the URL virtual path) as the root directory of the application.
The JSP container also defines default locations for JSP application resources. For example, application beans and classes in the application-relative /WEB-INF/classes and /WEB-INF/lib directories (servlet 2.2 or higher) will automatically be loaded by the Oracle JSP classloader without the need for specific configuration.
The servlet 2.0 specification does not have a clearly defined concept of a Web application and there is no defined relationship between servlet contexts and applications, as there is in later servlet specifications. In a servlet 2.0 environment such as JServ, there is only one servlet context object per JVM. A servlet 2.0 environment also has only one session object.
The globals.jsa file, however, provides support for multiple applications and multiple sessions in a Web server, particularly for use in a servlet 2.0 environment.
Where a distinct servlet context object would not otherwise be available for each application, the presence of a globals.jsa file for an application allows the Oracle JSP container to provide the application with a distinct ServletContext object.
Additionally, where there would otherwise be only one session object (with either one servlet context or across multiple servlet contexts), the presence of a globals.jsa file allows the Oracle JSP container to provide a proxy HttpSession object to the application. This prevents the possibility of session variable-name collisions with other applications, although unfortunately it cannot protect application data from being inspected or modified by other applications. This is because HttpSession objects must rely on the underlying servlet session environment for some of their functionality.
An application must be notified when a significant state transition occurs. For example, applications often want to acquire resources when an HTTP session begins and release resources when the session ends, or restore or save persistent data when the application itself is started or terminated.
In standard servlet and JSP technology, however, only session-based events are supported.
For applications that use a globals.jsa file, the Oracle JSP container extends this functionality with the following four events:
You can write event handlers in the globals.jsa file for any of these events that the server should respond to.
The session_OnStart event and session_OnEnd event are triggered at the beginning and end of an HTTP session, respectively.
The application_OnStart event is triggered for any application by the first request for that application within any single JVM. The application_OnEnd event is triggered when the Oracle JSP container unloads an application.
For more information, see "The globals.jsa Event Handlers".
This section is an overview of general syntax and semantics for a globals.jsa file.
Each event block in a globals.jsa file--a session_OnStart block, a session_OnEnd block, an application_OnStart block, or an application_OnEnd block--has an event start tag, an event end tag, and a body (everything between the start and end tags) that includes the event-handler code.
The following example shows this pattern:
<event:session_OnStart> <% This scriptlet contains the implementation of the event handler %> </event:session_OnStart>
The body of an event block can contain any valid JSP tags--standard tags as well as tags defined in a custom tag library.
The scope of any JSP tag in an event block, however, is limited to only that block. For example, a bean that is declared in a jsp:useBean tag within one event block must be redeclared in any other event block that uses it. You can avoid this restriction, however, through the globals.jsa global declaration mechanism--see "Global Declarations and Directives".
For details about each of the four event handlers, see "The globals.jsa Event Handlers".
JSP implicit objects are available in globals.jsa event blocks as follows:
application_OnStart block has access to the application object.application_OnEnd block has access to the application object.session_OnStart block has access to the application, session, request, response, page, and out objects.session_OnEnd block has access to the application and session objects.This example shows you a complete globals.jsa file, using all four event handlers.
<event:application_OnStart> <%-- Initializes counts to zero --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> </event:application_OnStart> <event:application_OnEnd> <%-- Acquire beans --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% application.log("The number of page hits were: " + pageCount.getValue() ); %> <% application.log("The number of client sessions were: " + sessionCount.getValue() ); %> </event:application_OnEnd> <event:session_OnStart> <%-- Acquire beans --%> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% sessionCount.setValue(sessionCount.getValue() + 1); activeSessions.setValue(activeSessions.getValue() + 1); %> <br> Starting session #: <%=sessionCount.getValue() %> <br> There are currently <b> <%= activeSessions.getValue() %> </b> active sessions <p> </event:session_OnStart> <event:session_OnEnd> <%-- Acquire beans --%> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% activeSessions.setValue(activeSessions.getValue() - 1); %> </event:session_OnEnd>
This section provides details about each of the four globals.jsa event handlers.
The application_OnStart block has the following general syntax:
<event:application_OnStart> <% This scriptlet contains the implementation of the event handler %> </event:application_OnStart>
The body of the application_OnStart event handler is executed when the Oracle JSP container loads the first JSP page in the application. This usually occurs when the first HTTP request is made to any page in the application, from any client. Applications use this event to initialize application-wide resources, such as a database connection pool or data read from a persistent repository into application objects.
The event handler must contain only JSP tags (including custom tags) and white space--it cannot contain static text.
Errors that occur in this event handler but are not processed in the event-handler code are automatically trapped by the Oracle JSP container and logged using the servlet context of the application. Event handling then proceeds as if no error had occurred.
The following application_OnStart example is from the "A globals.jsa Example for Application Events: lotto.jsp". In this example, the generated lottery numbers for a particular user are cached for an entire day. If the user re-requests the picks, he or she gets the same set of numbers. The cache is recycled once a day, giving each user a new set of picks. To function as intended, the lotto application must make the cache persistent when the application is being shut down, and must refresh the cache when the application is reactivated.
The application_OnStart event handler reads the cache from the lotto.che file.
<event:application_OnStart> <% Calendar today = Calendar.getInstance(); application.setAttribute("today", today); try { FileInputStream fis = new FileInputStream (application.getRealPath("/")+File.separator+"lotto.che"); ObjectInputStream ois = new ObjectInputStream(fis); Calendar cacheDay = (Calendar) ois.readObject(); if (cacheDay.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) { cachedNumbers = (Hashtable) ois.readObject(); application.setAttribute("cachedNumbers", cachedNumbers); } ois.close(); } catch (Exception theE) { // catch all -- can't use persistent data } %> </event:application_OnStart>
The application_OnEnd block has the following general syntax:
<event:application_OnEnd> <% This scriptlet contains the implementation of the event handler %> </event:application_OnEnd>
The body of the application_OnEnd event handler is executed when the Oracle JSP container unloads the JSP application. Unloading occurs whenever a previously loaded page is reloaded after on-demand dynamic re-translation (unless the JSP unsafe_reload configuration parameter is enabled), or when the JSP container, which itself is a servlet, is terminated by having its destroy() method called by the underlying servlet container. Applications use the application_OnEnd event to clean up application level resources or to write application state to a persistent store.
The event handler must contain only JSP tags (including custom tags) and white space--it cannot contain static text.
Errors that occur in this event handler but are not processed in the event-handler code are automatically trapped by the Oracle JSP container and logged using the servlet context of the application. Event handling then proceeds as if no error had occurred.
The following application_OnEnd example is from the "A globals.jsa Example for Application Events: lotto.jsp". In this event handler, the cache is written to file lotto.che before the application is terminated.
<event:application_OnEnd> <% Calendar now = Calendar.getInstance(); Calendar today = (Calendar) application.getAttribute("today"); if (cachedNumbers.isEmpty() || now.get(Calendar.DAY_OF_YEAR) > today.get(Calendar.DAY_OF_YEAR)) { File f = new File(application.getRealPath("/")+File.separator+"lotto.che"); if (f.exists()) f.delete(); return; } try { FileOutputStream fos = new FileOutputStream (application.getRealPath("/")+File.separator+"lotto.che"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(today); oos.writeObject(cachedNumbers); oos.close(); } catch (Exception theE) { // catch all -- can't use persistent data } %> </event:application_OnEnd>
The session_OnStart block has the following general syntax:
<event:session_OnStart> <% This scriptlet contains the implementation of the event handler %> Optional static text... </event:session_OnStart>
The body of the session_OnStart event handler is executed when the Oracle JSP container creates a new session in response to a JSP page request. This occurs on a per client basis, whenever the first request is received for a session-enabled JSP page in an application.
Applications might use this event for the following purposes:
Because the implicit out object is available to session_OnStart, this is the only globals.jsa event handler that can contain static text in addition to JSP tags.
The session_OnStart event handler is called before the code of the JSP page is executed. As a result, output from session_OnStart precedes any output from the page.
The session_OnStart event handler and the JSP page that triggered the event share the same out stream. The buffer size of this stream is controlled by the buffer size of the JSP page. The session_OnStart event handler does not automatically flush the stream to the browser--the stream is flushed according to general JSP rules. Headers can still be written in JSP pages that trigger the session_OnStart event.
Errors that occur in this event handler but are not processed in the event-handler code are automatically trapped by the Oracle JSP container and logged using the servlet context of the application. Event handling then proceeds as if no error had occurred.
The following example makes sure that each new session starts on the initial page (index.jsp) of the application.
<event:session_OnStart> <% if (!page.equals("index.jsp")) { %> <jsp:forward page="index.jsp" /> <% } %> </event:session_OnStart>
The session_OnEnd block has the following general syntax:
<event:session_OnEnd> <% This scriptlet contains the implementation of the event handler %> </event:session_OnEnd>
The body of the session_OnEnd event handler is executed when the Oracle JSP container invalidates an existing session. This occurs in either of the following circumstances:
session.invalidate() method.Applications use this event to release client resources.
The event handler must contain only JSP tags (including tag library tags) and white space--it cannot contain static text.
Errors that occur in this event handler but are not processed in the event-handler code are automatically trapped by the Oracle JSP container and logged using the servlet context of the application. Event handling then proceeds as if no error had occurred.
The following example decrements the "active session" count when a session is terminated.
<event:session_OnEnd> <%-- Acquire beans --%> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% activeSessions.setValue(activeSessions.getValue() - 1); %> </event:session_OnEnd>
In addition to holding event handlers, a globals.jsa file can be used to globally declare directives and objects for the JSP application. You can include JSP directives, JSP declarations, JSP comments, and JSP tags that have a scope parameter (such as jsp:useBean).
This section covers the following topics:
Directives used within a globals.jsa file serve a dual purpose:
globals.jsa file itself.A directive in a globals.jsa file becomes an implicit directive for all JSP pages in the application, although a globals.jsa directive can be overwritten for any particular page.
A globals.jsa directive is overwritten in a JSP page on an attribute-by-attribute basis. If a globals.jsa file has the following directive:
<%@ page import="java.util.*" bufferSize="10kb" %>
and a JSP page has the following directive:
<%@page bufferSize="20kb" %>
then this would be equivalent to the page having the following directive:
<%@ page import="java.util.*" bufferSize="20kb" %>
If you want to declare a method or data member to be shared across any of the event handlers in a globals.jsa file, use a JSP <%!... %> declaration within the globals.jsa file.
Note that JSP pages in the application do not have access to these declarations, so you cannot use this mechanism to implement an application library. Declaration support is provided in the globals.jsa file for common functions to be shared across event handlers.
Probably the most common elements declared in globals.jsa files are global objects. Objects declared in a globals.jsa file become part of the implicit object environment of the globals.jsa event handlers and all the JSP pages in the application.
An object declared in a globals.jsa file (such as by a jsp:useBean statement) does not need to be redeclared in any of the individual JSP pages of the application.
You can declare a global object using any JSP tag or extension that has a scope parameter, such as jsp:useBean or jml:useVariable. Globally declared objects must be of either session or application scope (not page or request scope).
Nested tags are supported. Thus, a jsp:setProperty command can be nested in a jsp:useBean declaration. (A translation error occurs if jsp:setProperty is used outside a jsp:useBean declaration.)
When a global object is used in a globals.jsa event handler, the position of its declaration is important. Only those objects that are declared before a particular event handler are added as implicit objects to that event handler. For this reason, developers are advised to structure their globals.jsa file in the following sequence:
The sample globals.jsa file below accomplishes the following:
globals.jsa file, as well as for all subsequent pages. 
By including the taglib directive in the globals.jsa file, the directive does not have to be included in any of the individual JSP pages of the application.
jsp:useBean statements).For an additional example of using globals.jsa for global declarations, see "A globals.jsa Example for Global Declarations: index2.jsp".
<%-- Directives at the top --%> <%@ taglib uri="oracle.jsp.parse.OpenJspRegisterLib" prefix="jml" %> <%-- Declare global objects here --%> <%-- Initializes counts to zero --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <%-- Application lifecycle event handlers go here --%> <event:application_OnStart> <% This scriptlet contains the implementation of the event handler %> </event:application_OnStart> <event:application_OnEnd> <% This scriptlet contains the implementation of the event handler %> </event:application_OnEnd> <event:session_OnStart> <% This scriptlet contains the implementation of the event handler %> </event:session_OnStart> <event:session_OnEnd> <% This scriptlet contains the implementation of the event handler %> </event:session_OnEnd> <%-- Declarations used by the event handlers go here --%>
This section has examples of how the Oracle globals.jsa mechanism can be used in servlet 2.0 environments to provide an application framework and application-based and session-based event handling. The following examples are provided:
For information about globals.jsa usage, see "Oracle JSP Application and Session Support for JServ".
This sample illustrates globals.jsa event handling through the application_OnStart and application_OnEnd event handlers. In this sample, numbers are cached on a per-user basis for the duration of the day. As a result, only one set of numbers is ever presented to a user for a given lottery drawing. In this sample, a user is identified by their IP address.
Code has been written for application_OnStart and application_OnEnd to make the cache persistent across application shutdowns. The sample writes the cached data to a file as it is being terminated and reads from the file as it is being restarted (presuming the server is restarted the same day that the cache was written).
<%@ page import="java.util.*, oracle.jsp.jml.*" %> <jsp:useBean id = "cachedNumbers" class = "java.util.Hashtable" scope = "application" /> <event:application_OnStart> <% Calendar today = Calendar.getInstance(); application.setAttribute("today", today); try { FileInputStream fis = new FileInputStream (application.getRealPath("/")+File.separator+"lotto.che"); ObjectInputStream ois = new ObjectInputStream(fis); Calendar cacheDay = (Calendar) ois.readObject(); if (cacheDay.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) { cachedNumbers = (Hashtable) ois.readObject(); application.setAttribute("cachedNumbers", cachedNumbers); } ois.close(); } catch (Exception theE) { // catch all -- can't use persistent data } %> </event:application_OnStart> <event:application_OnEnd> <% Calendar now = Calendar.getInstance(); Calendar today = (Calendar) application.getAttribute("today"); if (cachedNumbers.isEmpty() || now.get(Calendar.DAY_OF_YEAR) > today.get(Calendar.DAY_OF_YEAR)) { File f = new File(application.getRealPath("/")+File.separator+"lotto.che"); if (f.exists()) f.delete(); return; } try { FileOutputStream fos = new FileOutputStream (application.getRealPath("/")+File.separator+"lotto.che"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(today); oos.writeObject(cachedNumbers); oos.close(); } catch (Exception theE) { // catch all -- can't use persistent data } %> </event:application_OnEnd>
<%@ page session = "false" %> <jsp:useBean id = "picker" class = "oracle.jsp.sample.lottery.LottoPicker" scope = "page" /> <HTML> <HEAD><TITLE>Lotto Number Generator</TITLE></HEAD> <BODY BACKGROUND="images/cream.jpg" BGCOLOR="#FFFFFF"> <H1 ALIGN="CENTER"></H1> <BR> <!-- <H1 ALIGN="CENTER"> IP: <%= request.getRemoteAddr() %> <BR> --> <H1 ALIGN="CENTER">Your Specially Picked</H1> <P ALIGN="CENTER"><IMG SRC="images/winningnumbers.gif" WIDTH="450" HEIGHT="69" ALIGN="BOTTOM" BORDER="0"></P> <P> <P ALIGN="CENTER"> <TABLE ALIGN="CENTER" BORDER="0" CELLPADDING="0" CELLSPACING="0"> <TR> <% int[] picks; String identity = request.getRemoteAddr(); // Make sure its not tomorrow Calendar now = Calendar.getInstance(); Calendar today = (Calendar) application.getAttribute("today"); if (now.get(Calendar.DAY_OF_YEAR) > today.get(Calendar.DAY_OF_YEAR)) { System.out.println("New day...."); cachedNumbers.clear(); today = now; application.setAttribute("today", today); } synchronized (cachedNumbers) { if ((picks = (int []) cachedNumbers.get(identity)) == null) { picks = picker.getPicks(); cachedNumbers.put(identity, picks); } } for (int i = 0; i < picks.length; i++) { %> <TD> <IMG SRC="images/ball<%= picks[i] %>.gif" WIDTH="68" HEIGHT="76" ALIGN="BOTTOM" BORDER="0"> </TD> <% } %> </TR> </TABLE> </P> <P ALIGN="CENTER"><BR> <BR> <IMG SRC="images/playrespon.gif" WIDTH="120" HEIGHT="73" ALIGN="BOTTOM" BORDER="0"> </BODY> </HTML>
This example uses a globals.jsa file to process applications and session lifecycle events. It counts the number of active sessions, the total number of sessions, and the total number of times the application page has been hit. Each of these values is maintained at the application scope. The application page (index1.jsp) updates the page hit count on each request. The globals.jsa session_OnStart event handler increments the number of active sessions and the total number of sessions. The globals.jsa session_OnEnd handler decrements the number of active sessions by one.
The page output is simple. When a new session starts, the session counters are output. The page counter is output on every request. The final tally of each value is output in the globals.jsa application_OnEnd event handler.
Note the following in this example:
application scope.oracle.jsp.jml.JmlNumber extended datatype, which simplifies the use of data values at application scope. For information about the JML extended datatypes, refer to the Oracle9iAS Containers for J2EE JSP Tag Libraries and Utilities Reference.<%@ taglib uri="oracle.jsp.parse.OpenJspRegisterLib" prefix="jml" %> <event:application_OnStart> <%-- Initializes counts to zero --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <%-- Consider storing pageCount persistently -- If you do read it here --%> </event:application_OnStart> <event:application_OnEnd> <%-- Acquire beans --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% application.log("The number of page hits were: " + pageCount.getValue() ); %> <% application.log("The number of client sessions were: " + sessionCount.getValue() ); %> <%-- Consider storing pageCount persistently -- If you do write it here --%> </event:application_OnEnd> <event:session_OnStart> <%-- Acquire beans --%> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% synchronized (sessionCount) { sessionCount.setValue(sessionCount.getValue() + 1); %> <br> Starting session #: <%= sessionCount.getValue() %> <br> <% } %> <% synchronized (activeSessions) { activeSessions.setValue(activeSessions.getValue() + 1); %> There are currently <b> <%= activeSessions.getValue() %> </b> active sessions <p> <% } %> </event:session_OnStart> <event:session_OnEnd> <%-- Acquire beans --%> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% synchronized (activeSessions) { activeSessions.setValue(activeSessions.getValue() - 1); } %> </event:session_OnEnd>
<%-- Acquire beans --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <% synchronized(pageCount) { pageCount.setValue(pageCount.getValue() + 1); } %> This page has been accessed <b> <%= pageCount.getValue() %> </b> times. <p>
This example uses a globals.jsa file to declare variables globally. It is based on the event handler sample in "A globals.jsa Example for Application and Session Events: index1.jsp", but differs in that the three application counter variables are declared globally. (In the original event-handler sample, by contrast, each event handler and the JSP page itself had to provide jsp:useBean statements to locally declare the beans they were accessing.)
Declaring the beans globally results in implicit declaration in all event handlers and the JSP page.
<%-- globally declares variables and initializes them to zero --%> <jsp:useBean id="pageCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="sessionCount" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <jsp:useBean id="activeSessions" class="oracle.jsp.jml.JmlNumber" scope = "application" /> <event:application_OnStart> <%-- Consider storing pageCount persistently -- If you do read it here --%> </event:application_OnStart> <event:application_OnEnd> <% application.log("The number of page hits were: " + pageCount.getValue() ); %> <% application.log("The number of client sessions were: " + sessionCount.getValue() ); %> <%-- Consider storing pageCount persistently -- If you do write it here --%> </event:application_OnEnd> <event:session_OnStart> <% synchronized (sessionCount) { sessionCount.setValue(sessionCount.getValue() + 1); %> <br> Starting session #: <%= sessionCount.getValue() %> <br> <% } %> <% synchronized (activeSessions) { activeSessions.setValue(activeSessions.getValue() + 1); %> There are currently <b> <%= activeSessions.getValue() %> </b> active sessions <p> <% } %> </event:session_OnStart> <event:session_OnEnd> <% synchronized (activeSessions) { activeSessions.setValue(activeSessions.getValue() - 1); } %> </event:session_OnEnd>
<%-- pageCount declared in globals.jsa so active in all pages --%> <% synchronized(pageCount) { pageCount.setValue(pageCount.getValue() + 1); } %> This page has been accessed <b> <%= pageCount.getValue() %> </b> times. <p>
| 
 |  Copyright © 2000, 2002 Oracle Corporation. All Rights Reserved. | 
 |