Skip Headers

Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3) B25386-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 15.2 Using ADF Faces Cache to Cache Content

Consider using the `<afc:cache>` tag for the following types of content:

- Resource Intensive

  If rendering a particular JSF or ADF component requires resource-intensive operations like making database or network queries, caching can help to reduce the rendering cost by retrieving content from the cache as opposed to regenerating it.

- Shareable

  The cache can serve the same object to multiple users or sessions.

  The degree of sharing can be application wide or limited by certain properties, such as a bean property, user cookie, or request header.

- Changes infrequently

  Infrequently changing content is ideal to cache, because the cache can serve the content for a long period of time. The ADF Faces Cache expiration and invalidation mechanisms help to invalidate content in the cache. Use expiration when you can accurately predict when the source of the content will change; use invalidation for content that changes from a request.

  Because frequently changing content requires constant cache updates, this content is not ideal to cache.

Several of the pages in the SRDemo application use the `Cache` component to cache fragments. By analyzing how caching support was added to `SRCreate.jspx` and `SRFaq.jspx`, you can better understand how to cache fragments in your applications.

Figure 15-1 shows the `SRCreate.jspx` page. It contains four cacheable fragments:

- The first fragment contains content at the start of the page, including the text and link to the Frequently Asked Questions, the prompt to enter a basic description of your problem, and the `objectSeparator` component.

  This content is generic to all users.

- The second fragment contains the `panelForm` component for selecting an appliance, requiring a database query.

  This content varies by the user. The content is valid across all sessions for the same user.

- The third fragment contains the tabs, including the New Service Request tab.

  This content varies by the user. The content is valid across all sessions for the same user.

- The fourth fragment contains the Logout and Help menu item at the top of the page.

  This content is generic to all users.

Because these fragments are shareable by a given user across sessions or across all users, they are good caching candidates.

Figure 15-1 Create New Service Request Page in the SRDemo Application

Description of "Figure 15-1 Create New Service Request Page in the SRDemo Application"

Example 15-1 shows the code for the first fragment, the start of the page content.

Example 15-1 Start Page Content Fragment

    <!--Page Content Start-->
    <afc:cache duration="864000">
       <af:objectSpacer width="10" height="10"/>
       <af:panelHorizontal>
         <f:facet name="separator">
           <af:objectSpacer width="4" height="10"/>
         </f:facet>
         <af:outputText value="#{res['srcreate.faqText']}"/>
         <af:commandLink text=" #{res['srcreate.faqLink']}"
                                  action="dialog:FAQ" useWindow="true"
                                  immediate="true" partialSubmit="true"/>
       </af:panelHorizontal>
       <af:objectSpacer width="10" height="10"/>
       <af:outputFormatted value="#{res['srcreate.explainText']}"/>
       <af:objectSeparator/>
    </afc:cache>

The `duration` attribute for the `<afc:cache>` tag specifies 86,400 seconds before the fragment expires. When a fragment expires and client requests it, it is removed from the cache and then refreshed with new content.

Example 15-2 shows the code for the second fragment, the `panelForm` component for selecting your appliance.

Example 15-2 Appliance Selection Fragment

    <af:panelForm>
      <afc:cache duration="86400"
               varyBy="userInfo.userId">
       <af:panelLabelAndMessage valign="top"
                               label="#{res['srcreate.info.1']}">
        <af:selectOneListbox id="navList1" autoSubmit="false"
                             value="#{bindings.findAllProduct1.inputValue}"
                             size="6" required="true">
          <f:selectItems value="#{bindings.findAllProduct1.items}"/>
        </af:selectOneListbox>
       </af:panelLabelAndMessage>
      </afc:cache>

The attributes for the `<afc:cache>` tag specify the following:

- The `duration` attributes specifies 86,400 seconds before the fragment expires

- The `varyBy` attribute specifies which version of the fragment to display based on the `userInfo` bean. This attribute specifies to cache a version of the fragment for each user. The content is valid across sessions for the same user.

Example 15-3 shows the code for the third fragment, the tabs across the top of the page.

Example 15-3 Menu Tabs Fragment

    <f:facet name="menu1">
        <afc:cache duration="864000"
                   varyBy="userInfo.userId">
        <af:menuTabs var="menuTab" value="#{menuModel.model}">
          <f:facet name="nodeStamp">
            <af:commandMenuItem text="#{menuTab.label}"
                                action="#{menuTab.getOutcome}"
                                rendered="#{menuTab.shown and menuTab.type=='default'}"
                               disabled="#{menuTab.readOnly}"/>
          </f:facet>
        </af:menuTabs>
      </afc:cache>
    </f:facet>

The attributes for the `<afc:cache>` tag specify the following:

- The `duration` attribute specifies 86,400 seconds before the fragment expires

- The `varyBy` attribute specifies which version of the fragment to display based on the `userInfo` bean.

Example 15-4 shows the code for the last fragment, the Logout and Help menu items.

Example 15-4 Logout and Help Menu Fragment

    <f:facet name="menuGlobal">
        <afc:cache duration="86400">
          <af:menuButtons>
            <af:commandMenuItem text="#{res['srdemo.menu.logout']}"
                                action="GlobalLogout"
                                immediate="true"
                                icon="/images/logout.gif"/>
            <af:commandMenuItem text="#{res['srdemo.menu.help']}"
                                action="GlobalHelp"
                                immediate="true"
                                icon="/images/help.gif"/>
          </af:menuButtons>
        </afc:cache>
    </f:facet>

The `duration` attribute for the `<afc:cache>` tag specifies 86,400 seconds before the fragment expires.

Figure 15-2 shows the `SRFaq.jspx` page. Its content is shareable among all users.

Figure 15-2 Frequently Asked Questions Dialog in the SRDemo Application

Description of "Figure 15-2 Frequently Asked Questions Dialog in the SRDemo Application"

Example 15-5 shows the code for this page fragment.

Example 15-5 FAQ Fragment

    <f:view>
        <afc:cache duration="86400"
                   searchKeys="FAQ">
    ...FAQ Page Content...
       </afc:cache>
    </f:view>

The attributes for the `<afc:cache>` tag specify the following:

- The `duration` attribute specifies 86,400 seconds before the fragment expires

- The `searchKeys` attribute assigns this page fragment a search string of `FAQ`. You can invalidate this fragment using this search key.

  You use search keys to organize web pages and fragments into different groups. You can assign all the pages in a particular group with the same search key. For example, you can assign the search key `new_request` to all the pages that have something to do with creating a new service requests. To invalidate a group of objects, you submit an invalidation request that specifies the search key associated with that particular group. For example, if the invalidation request specifies the search key `new_request`, all the pages assigned the `new_request` search key will be invalidated. In the SRDemo application, the `SRFaq.jspx` page is the only page assigned a search key.

  When objects are marked as invalid and a client requests them, they are removed and then refreshed with new content.

## 15.2.1 How to Add Support for ADF Faces Cache

To use the `Cache` component, you add the ADF Faces Cache library to an application's project and apply the library to the specific JSP page.

To add the ADF Faces Cache library:

1. In the Application Navigator, select the project that you want to use the `Cache` component.

2. From the context menu, choose Project Properties.

   The Project Properties dialog opens.

3. Select the Libraries node.

4. On the Libraries page, click Add Library.

5. Locate the ADF Faces Cache library in the selection tree and click OK.

6. On the Libraries page, click OK.

7. For each JSP document or page, you plan to apply the `<afc:cache>` tag, add the following library syntax to the `<jsp:root>` tag:

       xmlns:afc="http://xmlns.oracle.com/adf/faces/webcache"

   You can now insert the `Cache` component from the Component Palette or use Code Insight to insert the `<afc:cache>` tag.

## 15.2.2 What Happens When You Cache Fragments

When you run an application containing the `<afc:cache>` tag, the content is not cached until there is an initial browser request for it. After the content is cached, the content is served from the cache. You can see when content is inserted into the cache and how many cache hits and misses result from fragment requests using a combination of the following tools:

- Logging

- AFC Statistics Servlet

- Visual Diagnostics

### 15.2.2.1 Logging

ADF Faces Cache leverages the Java Logging API (java.util.logging.Logger) to log events and error messages. These messages show the sequence of how objects are inserted and served from the cache.

Depending on the logging configuration specified in the `j2ee-logging.xml` file, logging information can display in the Log Window of JDeveloper and write to the `log.xml` file. The `j2ee-logging.xml` file specifies the directory path information for `log.xml`.

Example 15-6 shows log excerpts in which fragment `SRCreate.jspx` is initially requested and found not to be in the cache (`cache miss`) and inserted into the cache (`insert`). `SRCreate.jspx` is requested again, and served from the cache (`cache hit`).

Example 15-6 Log Sample

    fragment is SRCreate.jspx:_id13
    fragment (SRCreate.jspx:_id13) fetch: cache miss
    fragment (SRCreate.jspx:_id13) insert: cached for 86400 secs
    ...
    fragment is SRCreate.jspx:_id19
    fragment (SRCreate.jspx:_id19) fetch: cache hit
    ...

See Also: Section A.9 for further information about the `j2ee-logging.xml` file

### 15.2.2.2 AFC Statistics Servlet

The AFC Statistics servlet, shown in Figure 15-3, displays the following cache statistics. These statistics can help to provide an overall picture of cache throughput:

- Number of objects in cache–The number of objects stored in the cache.

- Number of cache hits–The number of requests served by objects in the cache.

- Number of cache misses–The number of cacheable requests that were not served by the cache. This number represents initial requests and requests for invalidated or expired objects that have been refreshed.

- Number of invalidation requests–The number of invalidation requests serviced by the cache.

- Number of documents invalidated–The total number of objects invalidated by the cache.

  The Number of invalidation requests and the Number of documents invalidated may not be the same. This difference can occur because one search key may apply to more than one object.

The Click here to Reset Stats link resets these statistics, except for Number of objects in cache.

Figure 15-3 AFC Statistics Servlet

Description of "Figure 15-3 AFC Statistics Servlet"

To enable the servlet:

1. Create the following entry in the `web.xml` file in the `/WEB-INF` directory of the application:

       <servlet>
          <servlet-name>AFCStatsServlet</servlet-name>
          <servlet-class>oracle.webcache.adf.servlet.AFCStatsServlet</servlet-class>
       </servlet>

2. Point your browser to the following URL:

       http://application_host:application_port/application-context-root/servlet/AFCStatsServlet

See Also: Topic "Viewing Cache Performance Statistics" in the JDeveloper online help for further information about the AFC Statistics servlet

### 15.2.2.3 Visual Diagnostics

The visual diagnostics feature enables you to visually display whether fragments are cache hits or cache misses. This feature demarcates fragment output with the HTML `<SPAN>` tag, using a class appropriate for its cache hit or cache miss status. By setting a distinct class style, you can visually determine whether fragments are stored in the cache.

While the SRDemo application does not use the visual diagnostics feature, you may find it useful for testing your applications.

See Also: Topic "Using Visual Diagnostics" in the JDeveloper online help for further information

## 15.2.3 What You May Need to Know

When you use AFC Statistics servlet, you may encounter the following problems:

- HTTP `404 Page Not Found` error code

  If you receive this error when accessing the servlet, it is most likely the result of a configuration issue.

  To resolve this problem, ensure the following lines are present in the `web.xml` file:

      <servlet>
         <servlet-name>AFCStatsServlet</servlet-name>
         <servlet-class>oracle.webcache.adf.servlet.AFCStatsServlet</servlet-class>
      </servlet>

- `Cache instance is not running` error

  This error occurs because the servlet has not started to monitor the cache. The servlet only starts to monitor the cache after the first object has been inserted into the cache and the cache instance is created.

  To workaround this error, select Click here to Reset Stats.