Oracle9iAS Containers for J2EE Support for JavaServer Pages Reference Release 2 (9.0.2) Part Number A95882-01 |
|
The primary Web application environment supplied with Oracle9i Application Server release 2 is Oracle9iAS Containers for J2EE (OC4J). In addition, an Apache JServ servlet environment is provided, and was the primary servlet environment in earlier releases of Oracle9i Application Server.
For those who use the JServ environment (presumably for backward compatibility), there are special considerations relating to servlet and JSP usage, as with any servlet 2.0 environment. This appendix covers these considerations.
The following topics are discussed:
This section provides information about configuring JServ to run JSP pages, covering the following topics:
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
for the JServ environment.
For general information about JSP configuration parameters for Oracle9iAS, see "JSP Configuration Parameters".
Table B-1 summarizes the configuration parameters supported by the original Oracle JSP front-end servlet, oracle.jsp.JspServlet
. This is the front-end used for the JServ environment. (OC4J uses the front-end servlet oracle.jsp.runtimev2.JspServlet
.) For each parameter, the table notes the following:
ojspc
options for pre-translation
Notes:
ojspc
options.
main_mode
, precompile_check
, and static_text_in_chars
parameters, offered for OC4J, are not available for JServ environments. For JServ, however, outputting static text as characters is the default.
This section describes configuration parameters for the JServ environment in more detail.
(boolean; default: false
)
This parameter allows the OC4J JSP container to work around limitations in the way JServ handles directory aliasing. For information about the current limitations, see "JServ 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 JSP container throws 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 JSP container to proceed and execute the page implementation class even if it cannot find the page source.
If bypass_source
is enabled, the container still checks 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 JSP default classpath for use during translation, compilation, or execution of JSP pages.
Overall, the 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 that are loaded through the path specified in the classpath
setting are loaded by the JSP class loader, not by the system class loader. During JSP execution, classes that are loaded by the JSP class loader cannot access (or be accessed by) classes that are loaded by the system class loader or by any other class loader.
Notes:
|
(boolean; default: true
)
This flag has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: true
)
Set this flag to false
to instruct the 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=true
, the 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 translator retranslates the page. With developer_mode=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=true
, The JSP container checks to see if such classes have been modified since being loaded by the 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 "Dynamic Page Retranslation and Class Reloading".
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(compiler executable; default: null
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
Set this flag to true
to direct the JSP container to output generic "404" messages for file-not-found conditions, and generic "500" messages for compilation errors.
This is in contrast 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 you use a globals.jsa
file 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 true
(default) 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 "JSP Application and Session Support for JServ".
(SQLJ translator executable and options; default: null
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
(boolean; default: false
)
This has the same use in JServ as in OC4J, but in JServ is false
by default. See "Configuration Parameter Descriptions".
(boolean; default: false
)
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 JSP container encodes request parameters and bean property settings. Otherwise, it 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 "Multibyte Parameter Encoding in JServ".
Note:
It is preferable to use the |
(boolean; default: false
)
By default, the JSP container restarts the application and sessions whenever a JSP page is dynamically retranslated and reloaded (which occurs when there is 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 to not restart the application after dynamic retranslations and reloads. This avoids having existing sessions become invalid. A true
setting is appropriate for deployment environments. The false
(default) setting is appropriate for development environments.
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).
(boolean; default: false
)
This has the same use in JServ as in OC4J. See "Configuration Parameter Descriptions".
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 Apache 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 -ser2class=true,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.
Using ojspc
for a JServ environment requires a different command. Use ojspc_jserv
instead of ojspc
. This executes the same class, oracle.jsp.tool.Jspc
, but is set up with a classpath appropriate for JServ.
The ojspc -staticTextInChars
option has no effect for JServ, because in a JServ environment static text is output as characters by default. You cannot disable this.
There are special considerations in running JSP pages in the JServ environment, because it is a servlet 2.0 environment. The servlet 2.0 specification lacks support for some significant features that are available in servlet 2.2 and higher environments.
For information about how to configure a JServ environment for JSP pages, see "Getting Started in a JServ Environment".
This section discusses the following considerations for the JServ environment:
The mod_jserv
component, supplied by Apache, delegates HTTP requests to JSP pages or servlets running in the JServ servlet container in a middle-tier JVM. The middle-tier environment may or may not be on the same physical host as the back-end Oracle9i database.
Communication between mod_jserv
and middle-tier JVMs uses the proprietary Apache JServ protocol (AJP) over TCP/IP. The mod_jserv
component can delegate requests to multiple JVMs in a pool for load balancing.
Refer to Apache documentation for mod_jserv
configuration information. This documentation is provided with Oracle9iAS.
JServ and other servlet 2.0 environments have no concept of application roots, because there is only a single application environment. The Web server doc root is effectively the application root. By default, JSP pages and servlets running in the JServ environment of the Oracle9i Application Server, which are routed through the Apache mod_jserv
module provided with JServ, use the Apache JServ doc root. This is typically some .../htdocs
directory. In addition, it is possible to specify "virtual" doc roots through alias
settings in the httpd.conf
configuration file.
The OC4J JSP container does, however, offer additional functionality regarding doc roots and application roots in the JServ environment. Through the OC4J JSP globals.jsa
mechanism, you can designate a directory under the doc root to serve as an application root for any given application. This is accomplished by placing a globals.jsa
file as a marker in the desired directory. See "Overview of globals.jsa Functionality" for more information.
The application root directory can be located in any of the following locations, listed in the order they are searched:
globals.jsa
file
Because the concept of a Web application is not well defined in the servlet 2.0 specification, in JServ there is only one servlet context per servlet container. Additionally, there is only one session object per servlet container.
OC4J, however, supports a special application framework for use in the JServ environment. It accomplishes this through a file, globals.jsa
, that you can use as an application marker. This allows distinct servlet contexts and session objects for each application.
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 JSP container in a JServ environment, is in the same zone as the servlet or servlets that you want your JSP pages to share a session with. 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, when you use a globals.jsa
file for an application, presumably in a servlet 2.0 environment such as JServ, 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 true
(default) setting of the JSP session_sharing
configuration 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 "JSP Application and Session Support for JServ".
Also see these sections for related information:
JSP dynamic includes (using the jsp:include
tag) and forwards (using the jsp:forward
tag) rely on request dispatcher functionality that is present in servlet 2.2 and higher environments, but not in servlet 2.0 environments.
The OC4J 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 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.2 or higher environment.
isThreadSafe
to true
or false
in the wrapper JSP page depends on whether the original servlet is thread-safe.
jsp:include
action or jsp:forward
action 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.)
Apache JServ 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 results 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 Apache JServ getRealPath()
method returns an incorrect value when processing a file under an alias directory.
The OC4J JSP container supports an Apache-specific configuration parameter, alias_translation
, that works around this limitation when you set it 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 jsp:include
or jsp:forward
tag 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/"
And assume there is a JSP page located as follows:
/private/foo/xxx.jsp
The following jsp:include
tag 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 possible to forward to or include pages or HTML files only within the same application (per the servlet 2.2 specification).
Notes:
|
This section describes Oracle extensions to support multibyte request parameters and bean property settings in a JServ or other servlet 2.0 environment, such as for a getParameter()
call in Java code or for a jsp:setProperty
tag to set a bean property in JSP code. There are two mechanisms for this:
oracle.jsp.util.PublicUtil.setReqCharacterEncoding()
static method (preferred)
translate_params
configuration parameter (or equivalent code)
The discussion of translate_params
is followed by a discussion of how to migrate away from its use when you move to an OC4J environment.
For general information about multibyte parameter encoding, see "JSP Support for Multibyte Parameter Encoding".
For pre-2.3 servlet environments, Oracle provides a setReqCharacterEncoding()
method that is useful in case the default encoding for the servlet container is not appropriate. Use this method to specify the encoding of multibyte request parameters and bean property settings, such as for a getParameter()
call in Java code or a jsp:setProperty
tag to set a bean property in JSP code. If the default encoding is already appropriate, then it is not necessary to use this method, and in fact using it may create some performance overhead in your application.
The setReqCharacterEncoding()
method is a static method in the PublicUtil
class of the oracle.jsp.util
package, with the following signature:
public static void setReqCharacterEncoding (HttpServletRequest req, String encoding) throws java.io.UnsupportedEncodingException
This method affects parameter names and values, specifically:
getParameter()
method output
getParameterValues()
method output
getParameterNames()
method output
jsp:setProperty
settings for bean property values
When invoking the method, input a request object and a string that specifies the desired encoding, as follows:
oracle.jsp.util.PublicUtil.setReqCharacterEncoding(request, "EUC-JP");
Set this boolean flag to true
to override servlet containers that do not encode multibyte (globalization support) request parameters or bean property settings. (The default setting is false
.) With a true
setting, the JSP container decodes and encodes request parameters and bean property settings. Otherwise, it returns the parameters from the servlet container unchanged.
Note that you should not enable translate_params
in any of the following circumstances:
Setting translate_params
to true
in this situation may cause incorrect results. As of this writing, however, it is known that JServ does not properly handle multibyte parameter encoding.
page
directive or setContentType()
method
translate_params
accomplishes is already present in the JSP page
(See "Code Equivalent to the translate_params Configuration Parameter".)
Setting translate_params
to true
overrides the insufficient functionality of servlet containers that cannot decode and encode multibyte request parameters and bean property settings. (For information about how to set JSP configuration parameters, see "Setting JSP Parameters in JServ".)
When this flag is enabled, the JSP container encodes the request parameters and bean property settings based on the character set of the response
object, as indicated by the response.getCharacterEncoding()
method.
There may be situations where you do not want to or cannot use the translate_params
configuration parameter. It is useful to be aware of equivalent functionality that you can implement through scriptlet code in the JSP page, for example:
<%@ page contentType="text/html; charset=EUC-JP" %> ... String paramName="XXYYZZ"; // where XXYYZZ is a multibyte string paramName = new String(paramName.getBytes(response.getCharacterEncoding()), "ISO8859_1"); String paramValue = request.getParameter(paramName); paramValue= new String(paramValue.getBytes("ISO8859_1"), "EUC-JP"); ...
This code accomplishes the following:
XXYYZZ
as the parameter name to search for. (Presume XX
, YY
, and ZZ
are three Japanese characters.)
ISO-8859-1
, the servlet container character set, so that the servlet container can interpret it. (First a byte array is created for the parameter name, using the character encoding of the request object.)
ISO-8859-1
encoding.)
EUC-JP
for further processing or output to the browser.
See the next two sections for a globalization sample that depends on translate_params
being enabled, and one that contains the equivalent code so that it does not depend on the translate_params
setting.
The following sample accepts a user name in Japanese characters and correctly outputs the name back to the browser. In a servlet environment that cannot encode multibyte request parameters, this sample depends on the JSP configuration setting of translate_params=true
.
Presume XXYY
is the parameter name (something equivalent to "user name" in Japanese) and AABB
is the default value (also in Japanese).
(See the next section for a sample that has the code equivalent of the translate_params
functionality, thereby not depending on the translate_params
setting.)
<%@ page contentType="text/html; charset=EUC-JP" %> <HTML> <HEAD> <TITLE>Hello</TITLE></HEAD> <BODY> <% //charset is as specified in page directive (EUC-JP) String charset = response.getCharacterEncoding(); %> <BR> encoding = <%= charset %> <BR> <% String paramValue = request.getParameter("XXYY"); if (paramValue == null || paramValue.length() == 0) { %> <FORM METHOD="GET"> Please input your name: <INPUT TYPE="TEXT" NAME="XXYY" value="AABB" size=20> <BR> <INPUT TYPE="SUBMIT"> </FORM> <% } else { %> <H1> Hello, <%= paramValue %> </H1> <% } %> </BODY> </HTML>
Following is the sample input:
and the sample output:
The following sample, as with the preceding sample, accepts a user name in Japanese characters and correctly outputs the name back to the browser. This sample, however, has the code equivalent of translate_params
functionality, so does not depend on the translate_params
setting.
Presume XXYY
is the parameter name (something equivalent to "user name" in Japanese) and AABB
is the default value (also in Japanese).
For an explanation of the critical code in this sample, see "Code Equivalent to the translate_params Configuration Parameter".
<%@ page contentType="text/html; charset=EUC-JP" %> <HTML> <HEAD> <TITLE>Hello</TITLE></HEAD> <BODY> <% //charset is as specified in page directive (EUC-JP) String charset = response.getCharacterEncoding(); %> <BR> encoding = <%= charset %> <BR> <% String paramName = "XXYY"; paramName = new String(paramName.getBytes(charset), "ISO8859_1"); String paramValue = request.getParameter(paramName); if (paramValue == null || paramValue.length() == 0) { %> <FORM METHOD="GET"> Please input your name: <INPUT TYPE="TEXT" NAME="XXYY" value="AABB" size=20> <BR> <INPUT TYPE="SUBMIT"> </FORM> <% } else { paramValue= new String(paramValue.getBytes("ISO8859_1"), "EUC-JP"); %> <H1> Hello, <%= paramValue %> </H1> <% } %> </BODY> </HTML>
The new "global includes" functionality in the OC4J JSP container in Oracle9iAS 9.0.2, described in "Oracle JSP Global Includes", is useful in migrating applications that have previously used translate_params
for globalization.
In this case, the globally included file can consist of a scriptlet similar to one of the following to achieve functionality that is equivalent to that of translate_params
:
or:
contentType
attribute of a JSP page
directive:
<% request.setCharacterEncoding(response.getCharacterEncoding()); %>
or:
<% String yourCharSet = yourLogicToDetermineCharset(); response.setContentType("text/html; charset="+yourCharSet); request.setCharacterEncoding(response.getCharcterEncoding()); // NOTE: The relative ordering of response.setContentType() // and request.setCharacterEncoding() is important. %>
OC4J supports a file, globals.jsa
, as a mechanism for implementing the JSP specification in a servlet 2.0 environment. Web applications and servlet contexts are not fully defined in the servlet 2.0 specification.
This section discusses the globals.jsa
mechanism and covers the following topics, including information about migrating away from globals.jsa
when you move to an OC4J environment:
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 a 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 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 will automatically be loaded by the 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 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 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, this functionality is extended 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 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 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)--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 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 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)--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 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 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 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 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)--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 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 that is declared in a globals.jsa
file (such as by a jsp:useBean
tag) need not 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 the standard jsp:useBean
tag or the JML useVariable
tag. Globally declared objects must be of either session
or application
scope (not page
or request
scope).
Nested tags are supported. Thus, a jsp:setProperty
tag can be nested in a jsp:useBean
tag. (A translation error occurs if jsp:setProperty
is used outside a jsp:useBean
tag.)
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 --%>
The OC4J JSP front-end servlet in Oracle9iAS release 2 no longer supports globals.jsa
. If an existing application uses globals.jsa
, you should migrate away from this usage. The following substitutions for globals.jsa
functionality are recommended:
globals.jsa
as an application marker, use standard WAR packaging to denote the application structure.
globals.jsa
start-session, end-session, start-application, and end-application events, use standard servlet 2.3 listener functionality. For example, equivalent capabilities are offered through the standard javax.servlet.ServletContextListener
and javax.servlet.http.HttpSessionListener
interfaces.
globals.jsa
for global variable declarations, make the declarations in a single source file and use "global include" functionality of the OC4J JSP engine, introduced in Oracle9iAS 9.0.2. See "Oracle JSP Global Includes".
If you cannot migrate your code immediately, an application that uses globals.jsa
can still run in OC4J if you use the previous oracle.jsp.JspServlet
front-end servlet instead of the new oracle.jsp.runtimev2.JspServlet
front-end. You can specify this in the <servlet>
element in the application web.xml
file, which overrides definitions in the OC4J global-web-application.xml
file. This should be for short-term use only, however, given that the new front-end servlet supports many new features and configuration parameters and offers improved performance.
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 "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, users are identified by their IP addresses.
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(); pageContext.setAttribute("today", today, PageContext.APPLICATION_SCOPE); 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(); pageContext.setAttribute( "cachedNumbers", cachedNumbers, PageContext.APPLICATION_SCOPE); } 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; pageContext.setAttribute("today", today, PageContext.APPLICATION_SCOPE); } 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 must provide jsp:useBean
tags to locally declare the beans they access.)
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. |
|