Skip Headers

Oracle9iAS Containers for J2EE JSP Tag Libraries and Utilities Reference
Release 2 (9.0.2)

Part Number A95883-01
Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

7
Web Object Cache Tags and API

This chapter describes the Web Object Cache, an application-level caching mechanism supplied with OC4J. For Web applications written in Java, you can use the Web Object Cache in conjunction with the Oracle9iAS Web Cache for increased speed and scalability.

This chapter includes the following topics:

For an overview of Web caching, including a discussion of the Oracle9iAS Web Cache and Oracle9i Application Server Java Object Cache, see "Overview of Oracle Caching Support for Web Applications".

Overview of the Web Object Cache

The OC4J Web Object Cache is a mechanism that allows Web applications written in Java to capture, store, reuse, post-process, and maintain the partial and intermediate results generated by a dynamic Web page, such as a JSP or servlet. For programming interfaces, it provides a tag library (for use in JSP pages) and a Java API (for use in servlets).

The Web Object Cache works at the Java level and is closely integrated with the HTTP environment of JSP and servlet applications. Cached objects might consist of HTML or XML fragments, XML DOM objects, or Java serializable objects.

Through the Web Object Cache programming interfaces, you can decide how to split Web pages into page blocks that define separate cache objects for finer control of caching. (The terms block and object are used somewhat interchangeably in this sense.) In this way, the application itself can control life span and other behavior of individual cache entities during runtime. Application developers have the best understanding of the life cycle patterns of their application Web pages, so are best suited to determine how to split pages into cache blocks. You can specify maintenance policies for partial results either declaratively in an external file, the cache policy descriptor, or programmatically within the application itself.

This section covers the following topics:

Benefits of the Web Object Cache


Note:

The Web Object Cache is useful in particular scenarios and does not replace the need for other caching mechanisms, including the Oracle9iAS Web Cache. For an overview of the Web Object Cache, and how it relates to the Oracle9iAS Web Cache and the Oracle9i Application Server Java Object Cache, including a discussion of when it is appropriate to use each one, see "Overview of Oracle Caching Support for Web Applications".


Using the Web Object Cache can significantly reduce the amount of time spent in constructing page blocks or Java objects in dynamic applications, such as those with expensive intermediate operations like querying a database and formatting or transforming the results. Subsequent queries pull the information out of the cache, so the query and formatting do not have to be repeated.

Furthermore, developers can closely control the cache programmatically, through API calls or custom JSP tags. This can include controlling when cache entries are created, what they are named, when they expire, which users can see which cached data, and what operations can be applied to cached data before the results are served to the user.

Some kinds of Web applications benefit more than others by using the Web Object Cache, depending on the nature and use of their data. For example, applications such as catalog and directory browsing, delayed stock quotes, and personalized portals would particularly benefit. Applications such as real-time stock trading or real-time stock quotes, however, would not benefit, because the data has to be updated so frequently that the overhead of the caching operations would outweigh the benefits. (In these circumstances, however, the Oracle9iAS Web Cache might still be useful because of its lighter overhead.)

In general, the Web Object Cache is most useful in the following situations:

Using the Web Object Cache in JSP pages, instead of in servlets, is particularly convenient. JSP code generation can save much of the development effort.

Web Object Cache Components

The Web Object Cache consists of two main components:

This section also provides a brief introduction to the Oracle9i Application Server Java Object Cache, which is the default cache repository of the Web Object Cache.

Cache Repository

The cache repository is the component that is responsible for data storage, data distribution, and cache expiration. There can be multiple repository implementations for a programmable Web cache (such as the Web Object Cache), depending on the tier and platform. For example, the file system might be used for secondary storage in the middle tier, and database tables for primary storage in the database tier.

The Web Object Cache uses the Oracle9i Application Server Java Object Cache as its default repository. This is a general-purpose caching service and API designed for Java application use, with objects being accessible by name.

The Java Object Cache is a powerful and flexible programming facility. There are no restrictions on the types of objects that can be cached or the original source of the objects--the management of each object is easily customizable. Each object has a set of attributes such as the following:

Objects can be invalidated as a group or individually.

For more information, see theOracle9iAS Containers for J2EE Services Guide.


Notes:

See "Configuration for Back-End Repository" for information about configuring the Java Object Cache or a file system as the back-end repository for the Web Object Cache.


Cache Programming Interfaces

The front-end caching interfaces are used through JSP pages and servlets to handle HTTP processing and to direct the semantics relating to the cache policy (rules and specifications determining how the cache works).

The OC4J Web Object Cache programming interfaces can be further divided as follows:

This chapter describes these programming interfaces and their interaction with the cache repository. Cache tags are described in "Web Object Cache Tag Descriptions". The underlying cache policy API is described in "Web Object Cache Servlet API Descriptions". In servlets, you will use the underlying API; in JSP pages, you will typically use the more convenient tags.

Cache Policy and Scope

The cache policy is a set of specifications determining details of the cache and how it will behave. This includes the following:

You can set cache policy specifications (per "Attributes for Policy Specification and Use") through any of the following:

A cache policy object--an instance of the oracle.jsp.jwcache.CachePolicy class--is created with policy settings based on these inputs. Because the expiration policy is part of the cache policy, each CachePolicy object includes an attribute that is an instance of the oracle.jsp.jwcache.ExpirationPolicy class.

Cache data can be of either session scope, where it is available to only the current HTTP session, or application scope, where it is available to all users of the application.

For example, consider an online banking application that caches the account balance. Only the current user is interested in this information, so session scope is appropriate.

By contrast, consider an online store with a welcome page that issues the same general product recommendations to all users. In this case, it is appropriate for the page to use a cache that has application scope.

Key Functionality of the Web Object Cache

This section discusses key areas of functionality of the Web Object Cache, covering the following:

Cache Block Naming--Implicit Versus Explicit

A cache block is associated with a cache block name, which can be determined either implicitly by the caching policy (generally advisable), or explicitly by your application code. For retrieval, to avoid regenerating the page fragment in question, there is a lookup of the cache block name.

For implicit naming, there are two inputs:

For most situations, implicit naming will result in names that are sufficiently informative, because the HTTP request usually includes all the inputs to the Web application (inputs that determine what the application should generate).

Explicit naming might be desirable in some cases, however, such as when a group of users needs to share the same data. In this case, because relevant identification information may not be available directly from the user's HTTP request, an implicit cache name would not be useful. Instead, you can write code to explicitly generate a cache name that identifies the group. Preferably, the name-generation logic should still use only request parameters as input, not other states existing inside the application. This makes the semantics easier to follow and the code easier to debug.

Following is an example of explicit naming. In the cache tag, note the name attribute with a JSP expression that calls someMethod() to set the cache block name:

<ojsp:cache policy="/WEB-INF/policy1.cpd" 
            name="<%= someObj.someMethod() %>" >
...static text...
<% // dynamic content ... %>
</ojsp:cache>

In the following example, because there is no name attribute in the cache tag, the cache block name will be determined implicitly according to the HTTP request and the cache policy:

<ojsp:cache policy="/WEB-INF/policy2.cpd" >
...static text...
<% // dynamic content ... %>
</ojsp:cache>

See "More About Cache Block Naming and the autoType Attribute" for more information.


Note:

Cache blocks can be nested. In this case, the logic of the inner cache block will be executed only when the content of the outer block must be regenerated.


Cloneable Cache Objects

The OC4J Web Object Cache provides an interface, oracle.jsp.jwcache.CloneableCacheObj, which you can implement in serializable cache objects that you want to be cloneable. For mutable objects that are cached without being serialized, cloning is useful in providing a complete and hierarchical copy of the cache object. This section explains the usefulness of cloneability, first covering some necessary background information.

Memory-Oriented Repositories Versus Secondary Storage Repositories

There are two categories of repositories that can be used as the back-end of the Web Object Cache:

A secondary storage repository requires Java serialization during cache operations. During storage to the cache, objects are serialized into the repository; during retrieval from the cache, they are deserialized into memory. Therefore, as a result of the serialization/deserialization process, a complete and distinct copy of the cache object is automatically created during each cache operation.

This is not the case when you store or retrieve cache objects to or from a memory-oriented repository. With a memory-oriented repository, the identical object in the user application will be stored to the cache, or the identical object in the cache will be retrieved for the user. By default, no copy is made. If there are multiple retrievals, all retrievals share the same object.

Advantages in Cloning Copies of Cache Objects

In many cases in your applications, you will want to ensure that different retrievals use different copies of a cache object. There are two key reasons for this:

To avoid these possible problems, use complete and hierarchical copies when you store and retrieve generic Java serializable data to or from a memory-oriented repository. "Complete and hierarchical" means copying not just the direct members referenced by the object, but also any indirect variables that are referenced. For example, assume an object Y has a java.util.Vector instance as a member variable. Cloning a complete and hierarchical copy involves copying not just the Vector instance itself, but also all mutable objects or elements referenced by the Vector instance.

Use of the CloneableCacheObject Interface

If you implement the CloneableCacheObject interface and its cloneCacheObj() method in your cache objects, then the Web Object Cache will automatically call cloneCacheObj() to make a complete and hierarchical copy of each cache object whenever it is stored to or retrieved from a memory-oriented cache repository.

One of the OC4J demos (using the useCacheObj tag to cache generic Java objects) demonstrates the use of a cloneable cache object.

Cache Block Runtime Functionality

During runtime, when a Web Object Cache cache tag is encountered, the tag handler checks whether a corresponding cache object exists and was created recently enough to reuse. If so, the code in the body of the tag is not executed; instead, the cache object is reused. But if the cache object does not exist or is too old, the tag body code will be executed to generate a new object (page fragment, XML DOM object, or Java serializable object). Then this freshly generated object will be captured, such as through special buffer writing or object passing, and stored into the cache.

If computations in content generation are costly, such as for a complicated database query, and the life span of the cache is appropriate, so that the cached data is reusable, then the Web Object Cache can save significant amounts of time and system resources. Application speed and throughput will be greatly improved.

Data Invalidation and Expiration

You can set up cache blocks to expire after a specified duration or at a specified time, or they can be invalidated explicitly by a method call or tag invocation.

Cache Block Expiration

Because cache blocks mainly consist of semi-static fragments of information, the Oracle implementation does not require a tightly coherent expiration model. A looser model typically provides acceptable results and requires less synchronization overhead.

There are two categories of expiration for data in Web Object Cache blocks:

Expiration details are determined by the settings of attributes in an instance of the oracle.jsp.jwcache.ExpirationPolicy class. This ExpirationPolicy object is an attribute of the CachePolicy object associated with the cache block. See "Expiration Policy Attributes".

In JSP pages, you can set ExpirationPolicy attributes through attributes of the Web Object Cache cache tags (such as cache, cacheXMLObj, or useCacheObj). In servlets, you can use methods of the ExpirationPolicy object directly. (See "ExpirationPolicy Methods".) Alternatively, you can set ExpirationPolicy attributes through a cache policy descriptor. (See "Cache Policy Descriptor".)

Cache Block Invalidation

Instead of depending on expiration to invalidate a cache, you can invalidate it explicitly in one of the following ways:

Attributes for Policy Specification and Use

This section describes cache policy attributes--specifically, attributes of the CachePolicy and ExpirationPolicy classes. You can set these attributes through custom tags in JSP pages, directly through the provided Java API in servlets, or through a cache policy descriptor file.

Cache Policy Attributes

Cache policies, introduced in "Cache Policy and Scope", consist of the details that determine how cache blocks behave. You can set cache policy attributes in several ways, as described in subsequent sections:

Specification of cache policy settings results in the creation of a cache policy object, which includes an expiration policy object as one of its attributes. Following is abbreviated code for the CachePolicy class (in package oracle.jsp.jwcache), for illustration purposes only, showing the names of the cache policy attributes.

class CachePolicy
{
   boolean ignoreCache;
   int scope;
   int autoType;
   String selectedParameters[];
   String selectedCookies[];
   Date reusableTimeStamp;
   long reusableDeltaTime;
   ExpirationPolicy expirationPolicy;
   String cacheRepositoryName;
   boolean reportException;
}


Note:

The names documented below for integer constants are for servlet usage. Different names may be used for the Web Object Cache tags. See "Web Object Cache cache Tag".


Attribute Descriptions

Table 7-1 describes cache policy object attributes.

Table 7-1 Cache Policy Attribute Descriptions  
Attribute Type Description

ignoreCache

boolean

This is for use during development only. When making frequent code changes, set this to true to disable the cache, typically so that results that were generated prior to your changes will not be returned.

default: false

scope

int

Specifies the scope of the cache. Use the integer constant SCOPE_SESSION for the cache block to be accessible only to the current HTTP session, or SCOPE_APP for the cache block to be accessible to all HTTP sessions of the application.

default: application

autoType

int

Specifies whether the cache block is named explicitly or implicitly, and how properties of the HTTP request are used in cache block naming (for implicit naming). The name is relevant in determining when the cache is reused for subsequent requests. See "More About Cache Block Naming and the autoType Attribute".

default: implicitly, according to the URI plus all parameters plus selected cookies (TYPE_URI_ALLPARAM)

selectedParameters[]

String []

These are selected request parameter names used in cache block naming; used in conjunction with autoType. See "More About Cache Block Naming and the autoType Attribute".

default: null

selectedCookies[]

String[]

Selected cookie names used in cache block naming; used in conjunction with autoType. See "More About Cache Block Naming and the autoType Attribute".

default: null

reusableTimeStamp

java.util.Date

An absolute time limit for cache usability, where any cache block created prior to that time will not be reused. Instead, data is regenerated, but the cache block is unaltered. See "More About reusableTimeStamp and reusableDeltaTime".

Note the following regarding reusableTimeStamp:

  • It can be expressed as milliseconds between midnight, January 1, 1970 and the desired absolute time limit, or as a java.util.Date instance. Additional convenient formats are available through the cache tag--see "Web Object Cache Tag Descriptions".

  • It takes precedence over reusableDeltaTime.

  • If its value is set as the integer constant REUSABLE_ALWAYS or the string constant REUSABLE_IGNORED, then cache entries are always reusable, for as long as they remain in the cache.

  • It is not available through the XML cache policy descriptor file.

default: always reusable

reusableDeltaTime

long

A relative time limit for cache usability, where a cache block is not reused if the difference between cache block creation time and current time is greater than reusableDeltaTime. Instead, data is regenerated, but the cache block is unaltered. See "More About reusableTimeStamp and reusableDeltaTime".

Note the following regarding reusableDeltaTime:

  • It is specified in seconds.

  • The reusableTimeStamp attribute overrides it.

  • If its value is set as the integer constant REUSABLE_ALWAYS or the string constant REUSABLE_IGNORED, then cache entries are always reusable, for as long as they remain in the cache.

default: always reusable

expirationPolicy

ExpirationPolicy

An expiration policy object (an instance of oracle.jsp.jwcache.ExpirationPolicy), which specifies circumstances under which the repository will remove cache blocks from storage.

default: the default expiration policy object

For information about expiration policy objects, parameters, and defaults, see "Expiration Policy Attributes".

cacheRepositoryName

String

The name of the cache repository. Each cache policy can use its own repository.

The configurations of cache repositories are defined in the /WEB-INF/wcache.xml file.

default: "DefaultCacheRepository"

reportException

boolean

A false setting results in most cache operation failures being silent, without any exception being reported to the browser.

Default: true

More About Cache Block Naming and the autoType Attribute

As discussed in "Cache Block Naming--Implicit Versus Explicit", cache blocks can be named either implicitly, sometimes called auto-naming, or explicitly, sometimes called user-naming.

More specifically, there are six ways for cache blocks to be named. Explicit naming is the first way. Specify this with an autoType setting of TYPE_USERSPECIFIED (an integer constant).

The other five ways are variations of implicit naming:

As an example, assume that you have developed a JSP page, welcome.jsp, with a personalized greeting for each user. The data with the personalized greeting is the only cache block in the page. Further assume that you have specified "request URI + selected parameters + selected cookies" naming, with user as the only selected parameter for cache block naming and no selected cookies for naming.

Now assume the page is requested as follows:

http://host:port/a.jsp?user=Amy

In this case, a.jsp?user=Amy becomes the cache block name.

Now assume that the page is later requested by another user, as follows:

http://host:port/a.jsp?user=Brian

This will not reuse the "Amy" cache, because the value of user is different. Instead, a new cache block is created with a.jsp?user=Brian as the name.

Now assume a later request by the first user, as follows:

http://host:port/a.jsp?mypar=3&user=Amy

Because the user is again Amy, this request will reuse the first cache, displaying Amy's customized information without having to regenerate it. The mypar parameter is irrelevant to the caching mechanism because you did not include it in the selectedParameters[] list of the cache policy object, presumably because you determined that the value of mypar is not relevant in terms of cachable page output.

Now assume the following subsequent request:

http://host:port/a.jsp?yourpar=4&user=Brian&hello=true&foo=barfly

Because the user is again Brian, this request will reuse the second cache, displaying Brian's customized information without having to regenerate it. The yourpar, hello, and foo parameters are irrelevant to the caching mechanism because you did not include them in the selectedParameters[] list of the cache policy object.

More About reusableTimeStamp and reusableDeltaTime

Be aware that the concept of reusable is different than the concept of time-to-live (TTL) and is intended for more advanced use. Time-to-live, which controls the general lifetime of a cache, is described in "Expiration Policy Attributes". Usually time-to-live is all that is required to appropriately limit the use of cached data.

The attributes for reusability--reusableTimeStamp and reusableDeltaTime--are intended for more specialized use and do not affect the expiration or invalidation of cached data. As an example, consider a situation where different users have different requirements for how up-to-date a Web report is. Assume that most users can accept a report produced anytime within the past day, and that they all want to be looking at the same version so they can compare figures. An appropriate TTL value, then, would be "one day".

Also presume, however, that there is a small group of privileged users for whom the data is much more time-sensitive. They want to have information that is no more than one hour old.

In this case, although TTL is set to "one day" for all users, there can be a reusableDeltaTime setting of "one hour" for the privileged users, which will result in the cache not being used for them if the data is more than one hour old. Remember, though, that reusableTimeStamp and reusableDeltaTime do not expire the cache or otherwise affect it--the cached data can still be used for non-privileged users, according to the time-to-live.

It is up to the application logic to set appropriate values of reusableTimeStamp and reusableDeltaTime for the privileged user group.

Expiration Policy Attributes

Expiration policies are introduced in "Data Invalidation and Expiration". Expiration policies contain the details that determine when cache blocks expire, at which point their data should no longer be used and the data should be regenerated instead. (Note that for most discussion, you can think of the expiration policies as being part of the cache policies.) ExpirationPolicy attributes, as with CachePolicy attributes, can be set in any of the following ways:

The following abbreviated code for the ExpirationPolicy class (in package oracle.jsp.jwcache), provided for illustration purposes only, shows the names of the expiration policy attributes.

class ExpirationPolicy
{
   int expirationType;
   long TTL;
   long timeInaDay;
   int dayInaWeek;
   int dayInaMonth;
   boolean writeThrough;
}

Table 7-2 describes the expiration policy object attributes.


Note:

The names documented below for integer constants are for servlet usage. Different names may be used for the Web Object Cache tags. See "Web Object Cache cache Tag".


Table 7-2 Expiration Policy Attribute Descriptions  
Attribute Type Description

expirationType

int

The type of expiration policy--one of the following (the TYPE_XXX values are integer constants):

  • time-to-live, specified with an expirationType setting of TYPE_TTL (also see the TTL attribute below)

  • daily, to expire within a day at a specified time, specified with an expirationType setting of TYPE_DAILY (also see the timeInaDay attribute below)

  • weekly, to expire within a week on a specified day at a specified time, specified with an expirationType setting of TYPE_WEEKLY (also see the timeInaDay and dayInaWeek attributes below)

  • monthly, to expire within a month on a specified date at a specified time, specified with an expirationType setting of TYPE_MONTHLY (also see the timeInaDay and dayInaMonth attributes below)

default: time-to-live

TTL

long

Time-to-live--the amount of time the cache block is good for, expressed in seconds.

default: 300 (5 minutes)

timeInaDay

long

The time of day used for daily, weekly, or monthly expiration, expressed in seconds from midnight--0 is 00:00:00 (midnight); 86399 is 23:59:59.

default: 300 (00:05:00); ignored if expirationType=TYPE_TTL

dayInaWeek

int

The day of the week for weekly expiration, at the specified timeInaDay--WEEKLY_SUNDAY, WEEKLY_MONDAY, WEEKLY_TUESDAY, WEEKLY_WEDNESDAY, WEEKLY_THURSDAY, WEEKLY_FRIDAY, or WEEKLY_SATURDAY (integer constants).

default: Wednesday; ignored unless expirationType=TYPE_WEEKLY

dayInaMonth

int

The date of the month for monthly expiration, such as 10 for the 10th of each month, at the specified timeInaDay. The maximum setting is the number of days in the month when the cache block is created. For example, if a cache block is created in June and dayInaMonth has a setting of 31, then its effective value will be 30.

default: 10; ignored unless expirationType=TYPE_MONTHLY

writeThrough

boolean

A flag specifying whether the cache repository should treat the cache entry as a write-through cache, writing it immediately into secondary storage such as a file system or database. Set this to true for write-through mode. A write-through cache will survive a server restart or power failure.

With a false setting, the cache entry is treated as a delayed-write cache, which is appropriate for caches that have a short life span, such as 5 or 10 minutes, and are not overly expensive to recompute.

default: true

Note: some cache repositories may not support write-through mode; others may always use write-through mode.

Web Object Cache Tag Descriptions

From JSP pages, you can specify cache policy settings, expiration policy settings, and explicit invalidation through custom tags provided with OC4J. Discussion is organized into the following categories:

The Web Object Cache classes are in the file ojsputil.jar, which is supplied with OC4J. Verify that this file is installed and in your classpath. Also, to use the Oracle9i Application Server Java Object Cache as the back-end repository, the file cache.jar must be installed and in your classpath. This file also comes with OC4J.

To use the Web Object Cache tags, the tag library description file, jwcache.tld, must be deployed with the application in the location specified in the taglib directives of your JSP pages, such as in the following example:

In an Oracle9i Application Server installation, the tag library description file is located in the [Oracle_Home]/j2ee/tlds directory.


Notes:


Cache Tag Descriptions

This section describes the following tags:

This section also describes conditional execution of code within the cache tags, possible resulting problems, and the workaround of dividing cache blocks into individual JSP pages and, optionally, using the cacheInclude tag to combine the pages together appropriately.

Web Object Cache cache Tag

This section documents the syntax and attributes of the cache tag, which you can use to set up general caching in a JSP application, in contrast to the caching of XML objects or Java serializable object.


Note:

For caching XML objects, use the cacheXMLObj tag instead. For caching Java serializable objects, use the useCacheObj tag. These tags support all the cache tag attributes described here. See "Web Object Cache cacheXMLObj Tag" and "Web Object Cache useCacheObj Tag".


Syntax

<ojsp:cache
   [ policy = "filename" ]
   [ ignoreCache = "true" | "false" ]
   [ invalidateCache = "true" | "false" ]
   [ scope = "application" | "session" ]
   [ autoType = "user" | "URI" | "URI_query" | "URI_allParam" |
                 "URI_selectedParam" | "URI_excludedParam" ]
   [ selectedParam = "space-delimited_string_of_parameter_names" ]
   [ selectedCookies = "space-delimited_string_of_cookie_names" ]
   [ reusableTimeStamp = "yyyy.mm.dd hh:mm:ss z" |
                         "yyyy.mm.dd hh:mm:ss" | "yyyy.mm.dd"| "ignored" ]
   [ reusableDeltaTime = "number" | "ignored" ]
   [ name = "blockname" ]
   [ expirationType = "TTL" | "daily" | "weekly" | "monthly" ]
   [ TTL = "number" ]
   [ timeInaDay = "number" ]
   [ dayInaWeek = "Sunday" | "Monday" | "Tuesday" | "Wednesday" |
                  "Thursday" | "Friday" | "Saturday" ]
   [ dayInaMonth = "number" ]
   [ writeThrough = "true" | "false" ]
   [ printCacheBlockInfo = "true" | "false" ]
   [ printCachePolicy = "true" | "false" ]
   [ cacheRepositoryName = "name" ]
   [ reportException = "true" | "false" ] >

...Code for cache block...

</ojsp:cache>


Notes:

  • This tag can optionally be in the form of a single tag with no body: <ojsp:cache ... />

  • Key default values are as follows: TTL 300 seconds; dayInaMonth 10 (10th of the month); cache repository name DefaultCacheRepository.


Attributes

Most of the parameters of the cache tag correspond to attributes in the CachePolicy or ExpirationPolicy class, described earlier in this chapter (as referenced below).

Usage Notes

Example: cache Tag

This example lists and caches a set of items, using the cache tag.

<%@ taglib uri="/WEB-INF/jwcache.tld" prefix="ojsp" %>
<title>listitem.jsp</title>
<%
   String itemid=request.getParameter("itemid");
   if (itemid==null) {
     out.println("Please select a category from the above drop down box.");
     return;
   }
%>
<% long l1=(new java.util.Date()).getTime(); %>
<ojsp:cache autoType="URI_selectedParam" selectedParam="itemid" 
  printCacheBlockInfo="true" printCachePolicy="true"
  policy="/WEB-INF/test-policy.cpd" 
>
   Item List: <b><%= itemid %></b><br>
   Time: <%= new java.util.Date() %>
   <br>
   <jsp:useBean class="java.util.Hashtable" id="table" scope="application" />
   <hr>
   <%
     Vector list=(Vector) table.get(itemid);
     if (list==null) {
       out.println("No such item!");
     }
     else {
       for (int i=0; i<list.size(); i++) {
   %>
   <%= list.elementAt(i) %><br>
   <%    
       }
     }
   %>
   timestamp:<%= new java.util.Date() %>
   <br>
</ojsp:cache>
<% long l2=(new java.util.Date()).getTime(); %>
Time for general cache operation:<%= l2-l1 %>
<br>

Web Object Cache cacheXMLObj Tag

Generally speaking, use the cacheXMLObj tag instead of the cache tag if you are caching XML DOM objects.

The cacheXMLObj tag supports all the cache tag attributes described in "Web Object Cache cache Tag", as well as the attributes described here.

Syntax (in addition to that of the cache tag)

<ojsp:cacheXMLObj
   ...
   [ fromXMLObjName = "objectname" ]
   [ toXMLObjName = "objectname" ]
   [ toWriter = "true" | "false" ] >

...Code for cache block...

</ojsp:cacheXMLObj>


Notes:

  • This tag can optionally be in the form of a single tag with no body: <ojsp:cacheXMLObj ... />

  • For convenience, this tag is duplicated in the XML tag library, defined in the xml.tld tag library description file.

  • This tag can act as both an XML producer and an XML consumer. Do not use fromXMLObjName and toXMLObjName if the XML object is being passed implicitly. (See "XML Producers and XML Consumers".)


Attributes (in addition to those of the cache tag)

Example: cacheXMLObj Tag

This example uses Web Object Cache tags, JESI tags, and tags from the XML and SQL tag libraries. (For JESI tag descriptions, see "Oracle JESI Tag Descriptions". For a description of the XML transform tag, see "XML Utility Tags". For SQL tag descriptions, see "SQL Tags for Data Access".)

The SQL dbOpen and SQL dbQuery tags connect to the database and execute a query. The cacheXMLObj tag caches the XML DOM object produced by the query--in subsequent executions (for output through different stylesheets, for example) the query does not have to be re-executed, because the DOM object can be retrieved from the Web Object Cache. The XML transform tag outputs the query results according to an XML stylesheet (specified through a variable). The JESI fragment tag encloses HTML output to be cached (which does not require application-level caching). The JESI template tag disables caching outside the fragment (through the cache="no" setting).

<jesi:template cache="no">
<% String userStyleLoc="style/rowset.xsl"; %>
<h3>Transform DBQuery Tag Example</h3>
<h4>Current Time=<%= new java.util.Date() %></h4>
<jesi:fragment expiration="60"> 
<!-- You can cache HTML in Oracle9iAS Web Cache with JESI
  or you can cache it in Oracle Web Object Cache -->
<h4>Cached Time=<%= new java.util.Date() %></h4>
<sql:dbOpen connId="conn1" URL="<%= connStr %>"
              user="scott" password="tiger" />
<xml:transform href="<%= userStyleLoc %>" > 
<%-- The XML DOM object is produced by dbQuery
  And, the DOM object is cached in Oracle Web Object Cache.
  XSLT is performed on the cached object. --%>
  <ojsp:cacheXMLObj TTL="60" toWriter="false">
    <sql:dbQuery connId="conn1" output="xml" queryId="myquery" >
       select ENAME, EMPNO from EMP 
    </sql:dbQuery>
  </ojsp:cacheXMLObj>
</xml:transform> 
<sql:dbCloseQuery queryId="myquery" />
<sql:dbClose connId="con1" />
</jesi:fragment>
</jesi:template>

Web Object Cache useCacheObj Tag

Use the useCacheObj tag to cache any Java serializable object.

The useCacheObj tag supports all the cache tag attributes described in "Web Object Cache cache Tag", as well as the attributes described here.

Syntax (in addition to that of the cache tag)

<ojsp:useCacheObj
   ...
     type="classname"
     id = "instancename" 
   [ cacheScope = "application" | "session" ] >

...Code for cache block...

</ojsp:useCacheObj>


Notes:

  • This tag can optionally be in the form of a single tag with no body: <ojsp:useCacheObj ... />

  • The id and type attributes are not request-time attributes, so cannot be set using JSP runtime expressions.


Attributes (in addition to those of the cache tag)

The type and id attributes here are used similarly to the type (or class) and id attributes in a standard jsp:useBean tag.

Example: useCacheObj Tag

<ojsp:useCacheObj id="a2" policy="/WEB-INF/test-policy.cpd" 
  type="examples.RStrArray" >
<%
   // create a temp writeable array 
   WStrArray tmpa2=new WStrArray(3);
   tmpa2.setStr(2,request.getParameter("testing4"));
   tmpa2.setStr(1,"def");
   tmpa2.setStr(0, (new java.util.Date()).toString() );
   // create a readonly copy for the cache
   a2=new RStrArray(tmpa2);  
   // storing the a2 into pagecontext
   // so useCacheObj tag can pick it up
   pageContext.setAttribute("a2",a2);
%>
</ojsp:useCacheObj>

Conditional Execution of Code Inside the Cache Tags

Be aware that code inside a cache tag (cache, cacheXMLObj, or useCacheObj) is executed conditionally. In particular:

If you are using the cache tag (not cacheXMLObj or useCacheObj), it might be helpful to break your cache blocks into separate JSP pages so that you would be less likely to fall into this type of situation. In this case, each cache block would be represented by its own URI, and you could use dynamic include functionality to combine the pages together as desired.

To make this more convenient, Oracle also provides the cacheInclude tag, described in "Web Object Cache cacheInclude Tag" below.

Web Object Cache cacheInclude Tag

The cacheInclude tag combines functionality of the cache tag (but not the cacheXMLObj tag or useCacheObj tag) and the standard jsp:include tag.

There are a number of advantages in putting cache blocks into separate pages and using cacheInclude, including general considerations of modularity and clarity as well as the issues discussed in "Conditional Execution of Code Inside the Cache Tags" above.

Be aware of the following limitations, however:

If any of these limitations presents a problem, then use separate cache and include tags.

Also be aware of an important difference between the cacheInclude tag and the JESI include tag. (See "JESI include Tag" for information about that tag.) Because the Oracle9iAS Web Cache is in a different caching layer than the Web Object Cache, the including page and included page for a JESI include tag cannot share the same request object. There is no such limitation with the cacheInclude tag, however--the including page and included page share the same request object, so beans and attributes of request scope can be passed between the two pages.

Syntax

<ojsp:cacheInclude
     policy = "filename"
     page = "URI"
   [ printCacheBlockInfo = "true" | "false" ] 
   [ reportException = "true" | "false" ] >

...Code for cache block...

</ojsp:cacheInclude>


Note:

For the cacheInclude tag, because policy and page are not request-time attributes, you do not have the option of determining their values through JSP expressions. (Be aware that policy is a request-time attribute for the cache, cacheXMLObj, and useCacheObj tags.)


Attributes

Usage Notes

Consider the following cacheInclude tag usage:

<ojsp:cacheInclude page="anotherPage.jsp" policy="foo.cpd" >

This is equivalent to the following:

<ojsp:cache policy="foo.cpd" >
   <% pageContext.include("anotherPage.jsp"); %>
</ojsp:cache>

or the following:

<jsp:include page="anotherPage.jsp" flush="true" />

where anotherPage.jsp consists of the following:

<ojsp:cache policy="foo.cpd" >
...anotherPage.jsp contents...
</ojsp:cache>

Cache Invalidation Tag Description

This section describes how to use the invalidateCache tag.

Web Object Cache invalidateCache Tag

To explicitly invalidate a cache block through program logic, you can use the invalidateCache tag. This section documents the syntax and attributes of this tag.


Notes:

  • The invalidateCache tag does not accept new cookies; it can use only existing cookies of the current HTTP request. For information about inputting new cookies, see "CachePolicy Methods".

  • Do not confuse the invalidateCache tag with the invalidateCache attribute of the cache tags. The attribute is for more limited use--to invalidate the pre-existing cache object.


Syntax

<ojsp:invalidateCache
   [ policy = "filename" ]
   [ ignoreCache = "true" | "false" ]
   [ scope = "application" | "session" ]
   [ autoType = "user" | "URI" | "URI_query" | "URI_allParam" |
                "URI_selectedParam" | "URI_excludedParam" ]
   [ selectedParam = "space-delimited_string_of_parameter_names" ]
   [ selectedCookies = "space-delimited_string_of_cookie_names" ]
   [ name = "blockname" ]
   [ invalidateNameLike = "true" | "false" ]
   [ page = "URI" ]
   [ autoInvalidateLevel = "application" | "page" | "param" | "cookie" ] 
   [ cacheRepositoryName = "name" ]
   [ reportException = "true" | "false" ] />


Note:

The default for autoInvalidateLevel depends on specifics of the page URI. See "Use of page and autoInvalidateLevel".


Attributes

Most parameters of the invalidateCache tag also exist in the cache and cacheXMLObj tags and are used in the same way, as described earlier in this chapter (and as referenced below).

Use of name and invalidateNameLike

To invalidate one or more cache blocks that were named through explicit cache-block naming, use the name and invalidateNameLike attributes together, as follows:

Use of page and autoInvalidateLevel

To invalidate one or more cache blocks that were named through implicit cache-block naming, use the page and autoInvalidateLevel attributes together, as follows:

Use the page attribute to specify the appropriate URI of the Web page. (With implicit naming, cache block names are based on Web page URIs.)

Use autoInvalidateLevel to specify the scope of invalidation--application scope, page scope, parameter scope, or cookie scope--as follows:

Example--Use of Cache Invalidation Tag

This section provides a brief example of cache invalidation. For complete sample applications, including cache invalidation, refer to the OC4J demos.

Example: invalidateCache Tag

The following page adds an item to a list of items previously cached, then invalidates the cache. The list will presumably be re-cached later with the new item.

<%@ taglib uri="/WEB-INF/jwcache.tld" prefix="ojsp" %>
<title>added.jsp</title>
<jsp:useBean class="java.util.Hashtable" id="table" scope="application" />
<%
   String itemid=request.getParameter("itemid");
   String addItem=request.getParameter("addItem");
   Vector list=(Vector) table.get(itemid);
   if (list==null) {
     list=new Vector();
     table.put(itemid,list);
   }
   list.addElement(addItem);
%>
<b><%= addItem %></b> was added into category <b><%= itemid %></b>.<br>
<% String viewPage="listitem.jsp?itemid="+itemid; %>
<% long l1=(new java.util.Date()).getTime(); %>
<ojsp:invalidateCache page="<%= viewPage %>" autoInvalidateLevel="param" 
  policy="/WEB-INF/test-policy.cpd"
    />
<% long l2=(new java.util.Date()).getTime(); %>
Existing cache entry has been invalidated. <br>
Invalidation took <%= l2-l1 %> milliseconds.
<br>
<jsp:include page="<%= viewPage %>" flush="true" />
<br>
<a href="seeitems.jsp" >Select items</a>
or
<a href="additem.html" >Add items</a>
<br>

Web Object Cache Servlet API Descriptions

From servlets, you can use CachePolicy methods to modify cache policy settings or to invalidate a cache block, and ExpirationPolicy methods to modify expiration settings. This requires creating a cache policy object and retrieving its expiration policy object attribute (which the JSP cache tag handlers do automatically).

This section discusses the following:

The Web Object Cache classes are in the file ojsputil.jar, which is supplied with OC4J. Verify that this file is installed and in your classpath. Also, to use the Oracle9i Application Server Java Object Cache as the back-end repository, the file cache.jar must be installed and in your classpath. This file also comes with OC4J.

For more information about the classes, interfaces, and methods described in this section, see the Javadoc that is supplied with OC4J.

Cache Policy Object Creation

There are two approaches to creating a CachePolicy object:

Using the lookupPolicy() Method

In most situations, the most convenient way to create a CachePolicy object is through the static lookupPolicy() method of the CacheClientUtil class, provided with OC4J, as in the following example:

CachePolicy cachePolicyObject = oracle.jsp.jwcache.CacheClientUtil.lookupPolicy
                             (servletConfig, request, "/WEB-INF/foo.cpd");

Input a servlet configuration object (a javax.servlet.ServletConfig instance), a request object (a javax.servlet.http.HttpServletRequest instance), and the URI path (relative to the application root) of an XML cache policy descriptor file.

Here is a simple example of a cache policy descriptor file:

<!-- 
test-policy.cpd 
-->

<cachePolicy scope="application">
<expirationPolicy expirationType="TTL" TTL="25" timeInaDay="00:10:00" 
writeThrough="true" />
</cachePolicy>

See "Cache Policy Descriptor" for more information.

Using a CachePolicy Constructor

The oracle.jsp.jwcache.CachePolicy class has the following public constructors--a simple constructor requiring only a servlet configuration object, a "copy" constructor that copies another CachePolicy object, and a "copy" constructor with a given servlet configuration object:

public CachePolicy(javax.servlet.ServletConfig config)

public CachePolicy(CachePolicy cPolicy)

public CachePolicy(javax.servlet.ServletConfig config,
                   CachePolicy cPolicy)

CachePolicy Methods

Several utility methods are available in CachePolicy objects, as well as getter and setter methods for key attributes.

CachePolicy Method Signatures and Common Parameters

The following abbreviated code, for illustration purposes only, contains signatures for key methods available in CachePolicy objects.

See "Cache Policy Attributes" for a discussion of relevant attributes.

class CachePolicy 
{
   boolean isRecent(CacheBlock block);
   void putCache(Object data, HttpServletRequest req, SectionId sectionId);
   void putCache(Object data, HttpServletRequest req, String specifiedName);
   void putAutoCacheForOtherPath(Object data, HttpServletRequest req,
                       String otherPath, StringSectionid sectionId);
   void putAutoCacheForOtherPath(Object data, HttpServletRequest req,
        String otherPath, Cookie[] newCookies, StringSectionid sectionId);
   CacheBlock getCache(HttpServletRequest req, SectionId sectionId);
   CacheBlock getCache(HttpServletRequest req, String specifiedName);
   CacheBlock getAutoCacheForOtherPath(HttpServletRequest req, 
                         String otherPath, StringSectionId sectionId);
   CacheBlock getAutoCacheForOtherPath(HttpServletRequest req, 
        String otherPath, Cookie[] newCookies, StringSectionId sectionId);
   void invalidateCache(HttpServletRequest req, SectionId sectionId);
   void invalidateCache(HttpServletRequest req, String specifiedName);
   void invalidateCacheLike(HttpServletRequest req, String specifiedName);
   void invalidateCacheLike(HttpServletRequest req, int autoInvalidateLevel);
   void invalidateCacheLike(HttpServletRequest req, String specifiedName,
                           int autoInvalidateLevel);
   void invalidateCacheOtherPathLike(HttpServletRequest req, String otherPath);
   void invalidateCacheOtherPathLike(HttpServletRequest req, String otherPath,
                         Cookie[] newCookies, int autoInvalidateLevel);
   Date getCurrentTime();
}

These methods use several common parameters:

CachePolicy Method Descriptions

The CachePolicy methods function as follows:

CachePolicy Getter and Setter Methods

You can use the following methods to retrieve or alter CachePolicy object attributes. See "Cache Policy Attributes" for a discussion of these attributes.

The following methods are also available, but are primarily intended for use by the Web Object Cache tag handlers:

Expiration Policy Object Retrieval

Each CachePolicy object has an ExpirationPolicy attribute. If you want to set expiration policies for a cache block, you can use the getExpirationPolicy() method of its CachePolicy object, as in the following example:

CachePolicy cachePolicyObj = CacheClientUtil.lookupPolicy
                             (config, request, "/WEB-INF/mypolicy.cpd");
ExpirationPolicy expPolicyObj = cachePolicyObj.getExpirationPolicy();

ExpirationPolicy Methods

The ExpirationPolicy class has getter and setter methods for its attributes, as follows. For descriptions of these attributes, see "Expiration Policy Attributes".

Additionally, the ExpirationPolicy class has the following utility method:

The ExpirationPolicy class also defines the following integer constants for the expirationType attribute:

And the following integer constants are defined for the dayInaWeek attribute:

CacheBlock Methods

You can use the getCache() method of a CachePolicy object to retrieve the associated CacheBlock object, as documented in "CachePolicy Methods" and shown in "Sample Servlet Using the Web Object Cache API" below.

The following abbreviated code, for illustrative purposes only, shows the key methods of the oracle.jsp.jwcache.CacheBlock class:

class CacheBlock
{  long getCreationTime();
   long getExpirationTime();
   Serializable getData();
}

Here are brief descriptions of these methods:

Sample Servlet Using the Web Object Cache API

The following sample servlet, DemoCacheServlet, uses the Web Object Cache. The code is followed by notes about some of its operations.

package demoPkg;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

import java.io.PrintWriter;
import java.io.CharArrayWriter;

import oracle.jsp.jwcache.CachePolicy;
import oracle.jsp.jwcache.ExpirationPolicy;
import oracle.jsp.jwcache.StringSectionId;
import oracle.jsp.jwcache.CacheBlock;
import oracle.jsp.jwcache.CacheClientUtil;

public class DemoCacheServlet extends HttpServlet{

  public void service(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException
  {
    // standard writer object from servlet engine
    PrintWriter out=response.getWriter();
    ServletConfig config=getServletConfig();

    try {
      CachePolicy cachePolicyObj = CacheClientUtil.lookupPolicy(config,request,
        "/WEB-INF/test-policy.cpd" );  // Note A
      StringSectionId sectionId=new StringSectionId("s1");   // Note B
      CacheBlock cacheBlockObj=null;

      cacheBlockObj = cachePolicyObj.getCache(request,sectionId); // Note C
      if (!cachePolicyObj.isRecent(cacheBlockObj)) {  // Note D
        CharArrayWriter newOut=new CharArrayWriter();    
        PrintWriter pw=new PrintWriter(newOut);
        
        // actual logic within a cache block 
        pw.println("fragment#1");
        pw.println(new java.util.Date());
        // which generates content into the "out" object
        
        if (cacheBlockObj == null) {   // Note E
          cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);  
          // Note F
        }
        
        out.write(newOut.toCharArray());
        // writing out newly created data back to the original writer
      }
      else {
        out.write((char[])cacheBlockObj.getData());  
        // writing the existing cached data to the writer
      }

      sectionId=new StringSectionId("s2");
      long timeToLive = 15;   // now set TTL to 15 on this block
      ExpirationPolicy expirationPolicy = cachePolicyObj.getExpirationPolicy();
      expirationPolicy.setTTL(timeToLive);
      cachePolicyObj.setExpirationPolicy(expirationPolicy);
      cacheBlockObj = cachePolicyObj.getCache(request,sectionId);
      if (!cachePolicyObj.isRecent(cacheBlockObj)) { 
        CharArrayWriter newOut=new CharArrayWriter();    
        PrintWriter pw=new PrintWriter(newOut);
        
        // actual logic within a cache block 
        pw.println("fragment#2");
        pw.println(new java.util.Date());
        // which generates content into the "out" object
        
        if (cacheBlockObj == null) { 
          cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);  
        }
        
        out.write(newOut.toCharArray());
        // writing out newly created data back to the original writer
      }
      else {
        out.write((char[])cacheBlockObj.getData());  
        // writing the existing cached data to the writer
      }

    } catch (Throwable th) {
      // your exception handling code here
      th.printStackTrace(out);
    }
  }
}

Code Notes

The following notes describe some of the key functionality of the preceding example:

Tag Code Versus API Code

This example presents code for three approaches to an application that caches and presents timestamp output from two cache fragments:

Following the three code samples is a listing of the cache policy descriptor, test-policy.cpd.

In each approach, the application will cache the two fragments it displays. You can reload repeatedly, but the times displayed in the fragments will not change until the cached fragments expire. The first fragment takes 25 seconds to expire, getting the 25-second time-to-live value from the TTL setting in the cache policy descriptor (test-policy.cpd). The second fragment takes 15 seconds to expire, overriding the cache policy descriptor time-to-live value with a value set directly in the page code.

Output for the sample applications looks something like the following:

fragment#1  (expires in 25 seconds as per TTL value test-policy)
Sun May 27 15:20:46 PDT 2001

fragment#2 (expires in 15 seconds because TTL overrides test-policy value)
Sun May 27 15:20:46 PDT 2001

Simple JSP Page--tagcode.jsp

<%@ taglib uri="/WEB-INF/jwcache.tld" prefix="ojsp" %>
<title>tagcode.jsp</title>
<pre>
tagcode.jsp
<ojsp:cache policy="/WEB-INF/test-policy.cpd" >
  fragment#1  (expires in 25 seconds as per TTL value test-policy)
  <%= new java.util.Date() %>
</ojsp:cache>
<ojsp:cache policy="/WEB-INF/test-policy.cpd" TTL="15" >
  fragment#2 (expires in 15 seconds because TTL overrides test-policy value)
  <%= new java.util.Date() %>
</ojsp:cache>
</pre>

Scriptlet JSP Page--servletcode.jsp

Code notes are the same as for the servlet version below, which is repeated and described in "Sample Servlet Using the Web Object Cache API".

<%@ page import="oracle.jsp.jwcache.*,java.io.*" %>
<title>servletcode.jsp</title>
<pre>
servletcode.jsp
<%
  CachePolicy cachePolicyObj = CacheClientUtil.lookupPolicy(config,request,
   "/WEB-INF/test-policy.cpd" );  // Note A
  StringSectionId sectionId=new StringSectionId("s1");   // Note B
  CacheBlock cacheBlockObj=null;
  
  cacheBlockObj = cachePolicyObj.getCache(request,sectionId); // Note C
  if (!cachePolicyObj.isRecent(cacheBlockObj)) {  // Note D
    CharArrayWriter newOut=new CharArrayWriter();    
    PrintWriter pw=new PrintWriter(newOut);

    // actual logic within a cache block 
    pw.println
("fragment#1 (expires in 25 seconds as per TTL value test-policy)");
    pw.println(new java.util.Date());
    // which generates content into the "out" object

    if (cacheBlockObj == null) {   // Note E
      cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);  
      // Note F
    }
    
    out.write(newOut.toCharArray());
    // writing out newly created data back to the original writer
  }
  else {
    out.write((char[])cacheBlockObj.getData());
    // writing the existing cached data to the writer
  }

  sectionId=new StringSectionId("s2");
  long timeToLive = 15;   // now set TTL to 15 on this block
  ExpirationPolicy expirationPolicy = cachePolicyObj.getExpirationPolicy();
  expirationPolicy.setTTL(timeToLive);
  cachePolicyObj.setExpirationPolicy(expirationPolicy);
  cacheBlockObj = cachePolicyObj.getCache(request,sectionId); 
  if (!cachePolicyObj.isRecent(cacheBlockObj)) { 
    CharArrayWriter newOut=new CharArrayWriter();    
    PrintWriter pw=new PrintWriter(newOut);

    // actual logic within a cache block 
    pw.println
("fragment#2 (expires in 15 seconds because TTL overrides test-policy value)");
    pw.println(new java.util.Date());
    // which generates content into the "out" object

    if (cacheBlockObj == null) {  
      cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);
    }
    
    out.write(newOut.toCharArray());
    // writing out newly created data back to the original writer
  }
  else {
    out.write((char[])cacheBlockObj.getData());  
    // writing the existing cached data to the writer
  }

%>
</pre>

Servlet Page--DemoCacheServlet.java

This sample also appears in "Sample Servlet Using the Web Object Cache API". Refer there for information about the code notes.

package demoPkg;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

import java.io.PrintWriter;
import java.io.CharArrayWriter;

import oracle.jsp.jwcache.CachePolicy;
import oracle.jsp.jwcache.ExpirationPolicy;
import oracle.jsp.jwcache.StringSectionId;
import oracle.jsp.jwcache.CacheBlock;
import oracle.jsp.jwcache.CacheClientUtil;

public class DemoCacheServlet extends HttpServlet{

  public void service(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException
  {
    // standard writer object from servlet engine
    PrintWriter out=response.getWriter();
    ServletConfig config=getServletConfig();

    try {
      CachePolicy cachePolicyObj = CacheClientUtil.lookupPolicy(config,request,
        "/WEB-INF/test-policy.cpd" );  // Note A
      StringSectionId sectionId=new StringSectionId("s1");   // Note B
      CacheBlock cacheBlockObj=null;

      cacheBlockObj = cachePolicyObj.getCache(request,sectionId); // Note C
      if (!cachePolicyObj.isRecent(cacheBlockObj)) {  // Note D
        CharArrayWriter newOut=new CharArrayWriter();    
        PrintWriter pw=new PrintWriter(newOut);
        
        // actual logic within a cache block 
        pw.println("fragment#1");
        pw.println(new java.util.Date());
        // which generates content into the "out" object
        
        if (cacheBlockObj == null) {   // Note E
          cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);  
          // Note F
        }
        
        out.write(newOut.toCharArray());
        // writing out newly created data back to the original writer
      }
      else {
        out.write((char[])cacheBlockObj.getData());  
        // writing the existing cached data to the writer
      }

      sectionId=new StringSectionId("s2");
      long timeToLive = 15;   // now set TTL to 15 on this block
      ExpirationPolicy expirationPolicy = cachePolicyObj.getExpirationPolicy();
      expirationPolicy.setTTL(timeToLive);
      cachePolicyObj.setExpirationPolicy(expirationPolicy);
      cacheBlockObj = cachePolicyObj.getCache(request,sectionId);
      if (!cachePolicyObj.isRecent(cacheBlockObj)) { 
        CharArrayWriter newOut=new CharArrayWriter();    
        PrintWriter pw=new PrintWriter(newOut);
        
        // actual logic within a cache block 
        pw.println("fragment#2");
        pw.println(new java.util.Date());
        // which generates content into the "out" object
        
        if (cacheBlockObj == null) { 
          cachePolicyObj.putCache(newOut.toCharArray(),request,sectionId);
        }
        
        out.write(newOut.toCharArray());
        // writing out newly created data back to the original writer
      }
      else {
        out.write((char[])cacheBlockObj.getData());  
        // writing the existing cached data to the writer
      }

    } catch (Throwable th) {
      // your exception handling code here
      th.printStackTrace(out);
    }
  }
}

Cache Policy Descriptor--test-policy.cpd

This cache policy descriptor is used by all three approaches to the sample application--tagcode.jsp, servletcode.jsp, and DemoCacheServlet.java:

<!-- 
test-policy.cpd 
-->

<cachePolicy scope="application">
<expirationPolicy expirationType="TTL" TTL="25" timeInaDay="00:10:00" 
writeThrough="true" />
</cachePolicy>

Cache Policy Descriptor

You can optionally use an XML-style cache policy descriptor to specify attribute settings for the CachePolicy and ExpirationPolicy objects. In any JSP pages or servlets that you use, you would then specify the cache policy descriptor through the policy attribute of a cache, cacheXMLObj, useCacheObj, cacheInclude, or invalidateCache tag.

This section provides the cache policy descriptor DTD, a sample cache policy descriptor, and information about loading and refreshing the cache policy descriptor.

Cache Policy Descriptor DTD

This section provides a listing of the Web Object Cache cache policy descriptor DTD, cachepolicy.dtd. For an example of a cache policy descriptor, see "Sample Cache Policy Descriptor".

<!--
Copyright 2000 Oracle Corporation
cachepolicy.dtd
-->
<!--
This DTD is used to validate any (Oracle programmable web) 
cache policy descriptors (e.g. "/WEB-INF/foo.cpd").
-->

<!--
The cachePolicy element is the root element of cache policy descriptors.
configuration descriptor.
-->

<!ELEMENT cachePolicy (
   selectedParam*, selectedCookie*, 
   reusableTimeStamp?, reusableDeltaTime?,
   cacheRepositoryName?, expirationPolicy? ) >

<!ATTLIST cachePolicy ignoreCache (true | false) "false" >
<!ATTLIST cachePolicy scope (application | session) "application" >
<!ATTLIST cachePolicy autoType 
   (user | URI | URI_query |
    URI_allParam | URI_selectedParam | URI_excludedParam )
    "URI_allParam" >
<!ATTLIST cachePolicy reportException (true | false) "true" >

<!ELEMENT selectedParam (#PCDATA) >
<!ELEMENT selectedCookie (#PCDATA) >
<!ELEMENT reusableTimeStamp (#PCDATA) >
<!ELEMENT reusableDeltaTime (#PCDATA) >
<!ELEMENT cacheRepositoryName (#PCDATA) >

<!ELEMENT expirationPolicy EMPTY >

<!ATTLIST expirationPolicy expirationType (TTL | daily | weekly | monthly) 
         "TTL" >
<!ATTLIST expirationPolicy TTL CDATA "300" >
<!ATTLIST expirationPolicy timeInaDay CDATA #IMPLIED >
<!ATTLIST expirationPolicy dayInaWeek 
   (Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday) 
   "Wednesday" >
<!ATTLIST expirationPolicy dayInaMonth CDATA "10" > 
<!ATTLIST expirationPolicy writeThrough (true | false) "true" > 

Sample Cache Policy Descriptor

This section provides an example of a simple cache policy descriptor that sets the TTL and timeInaDay attributes. For the DTD, see "Cache Policy Descriptor DTD" above.

<!-- 
test-policy.cpd 
-->

<cachePolicy scope="application">
<expirationPolicy expirationType="TTL" TTL="25" timeInaDay="00:10:00" 
writeThrough="true" />
</cachePolicy>

Cache Policy Descriptor Loading and Refreshing

To create a CachePolicy object from an XML cache policy descriptor file, there must be a call to the static lookupPolicy() method of the oracle.jsp.jwcache.CacheClientUtil class. For JSP pages, this is handled automatically. For servlets, you must include the lookupPolicy() call in your code--see "Sample Servlet Using the Web Object Cache API".

If the caching policy has not been previously loaded, then the lookupPolicy() method results in the XML descriptor being parsed and used in constructing a new CachePolicy object (and an ExpirationPolicy attribute of this object). See "Cache Policy Object Creation" for information about the lookupPolicy() method.

The CachePolicy object is stored indirectly under the ServletContext object associated with your application. When the same caching policy is requested again, the stored policy object will be returned without the descriptor being re-read or re-parsed. For performance reasons, because the cache policy descriptor files are seldom changed, as well as for security reasons, OC4J does not provide descriptor auto-reloading functionality. The resulting cache policy object is stored in the middle-tier JVM for faster access.

The CachePolicy object will be valid until the servlet context is destroyed or someone calls the static refreshPolicy() method of the CacheClientUtil class. This method has the same calling sequence as the lookupPolicy() method. For example:

oracle.jsp.jwcache.CacheClientUtil.refreshPolicy
                   (servletConfig, request, "/WEB-INF/foo.cpd");

When you alter and refresh the caching policy, active cache blocks are not affected.

Cache Repository Descriptor

Use an XML-style cache repository descriptor to specify what to use as the back-end cache repository for the Web Object Cache, and how to configure it. This section supplies the DTD for cache repository descriptors, as well as a sample cache repository descriptor.


Note:

By default, the Web Object Cache uses the Oracle9i Application Server Java Object Cache as its cache repository.


Cache Repository Descriptor DTD

This section provides a listing of the Web Object Cache cache repository descriptor DTD, wcache.dtd. For an example of a cache repository descriptor, see "Sample Cache Repository Descriptor" below.

<!--
Copyright 2000 Oracle Corporation
wcache.dtd
-->
<!--
This DTD is used to validate "/WEB-INF/wcache.xml", which is used to hold
web cache repositories configuration information for 
Oracle programmable web caching components.
-->

<!--
The wcache-config element is the root element of web cache repositories 
configuration descriptor.
-->

<!ELEMENT wcache-config (cache-repository*)>

<!ELEMENT cache-repository 
(cache-repository-name,cache-repository-class,init-param*)>

<!ELEMENT cache-repository-name (#PCDATA)>
<!ELEMENT cache-repository-class (#PCDATA)>

<!ELEMENT init-param (param-name,param-value)>
<!ELEMENT param-name (#PCDATA)>
<!ELEMENT param-value (#PCDATA)>

Sample Cache Repository Descriptor

This section lists the cache repository descriptor provided with OC4J. For the DTD, see "Cache Repository Descriptor DTD" above.


Note:

The DTD does not include reporoot, which is a specific-use parameter that only a file system cache implementation requires.


<wcache-config>

<cache-repository>
   <cache-repository-name>DefaultCacheRepository</cache-repository-name>
   <cache-repository-class>
      oracle.jsp.jwcache.repository.impl.OCSRepoImpl
   </cache-repository-class>
</cache-repository>

<cache-repository>
   <cache-repository-name>SimpleFSRepo</cache-repository-name>
   <cache-repository-class>
      oracle.jsp.jwcache.repository.impl.SimpleFSRepositoryImpl
   </cache-repository-class>
   <init-param>
      <param-name>reporoot</param-name>
      <param-value>/tmp/reporoot</param-value>
   </init-param>
</cache-repository>

</wcache-config>

Configuration for Back-End Repository

This section describes how to configure the Oracle9i Application Server Java Object Cache or a file system as the back-end repository for the OC4J Web Object Cache.

Configuration Notes for Oracle9i Application Server Java Object Cache

The following preparatory steps are required in order to use the default cache repository, Oracle9i Application Server Java Object Cache, in an OC4J environment:

  1. Edit global-web-application.xml to add an initialization parameter to specify the location of the Java Object Cache configuration file, OCS4J.properties.

    For example, for a UNIX system:

    <servlet>
       <servlet-name>jsp</servlet-name>
       <servlet-class>oracle.jsp.runtimev2.JspServlet</servlet-class>
       <init-param>
          <param-name>ocs4j_file</param-name>
          <param-value>
             <your_install_root>/demo/ojspdemos/ojspdemos-web/WEB-INF/misc-file/OCS4J.properties
          </param-value>
       </init-param>
    </servlet>
    
    


    Notes:

    • The Java Object Cache cache.jar file must be available in the <your_install_root>/lib directory.

    • The misc-file directory is created automatically when you extract the demo programs.


  2. Update OCS4J.properties as appropriate. To set a root directory for the Java Object Cache, update the diskPath entry.

    For a UNIX system, do this as in the following example:

    diskPath = /mydir/ocs4jdir
    
    

    or, for a Windows NT system (note that you have to specify a drive letter):

    diskPath = c:\mydir\ocs4jdir
    
    

  3. Restart the Web server.

Configuration Notes for File System Cache

To use a file system as the back-end repository, edit the cache repository descriptor (wcache.xml) to set reporoot to specify a root directory for the file system cache. (This file is located in the WEB-INF directory where the OC4J samples are installed. See "Cache Repository Descriptor" for general information and for an example of a cache repository descriptor that sets a reporoot value.)

For example, for a UNIX system:

<init-param>
   <param-name>reporoot</param-name>
   <param-value>/mydir/repositoryroot</param-value>
</init-param>

or for a Windows NT system:

<init-param>
   <param-name>reporoot</param-name>
   <param-value>c:\mydir\repositoryroot</param-value>
</init-param>


Go to previous page Go to next page
Oracle
Copyright © 2002 Oracle Corporation.

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