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. |
|