|Oracle9i Application Server Application Developer's Guide
Release 2 (9.0.2)
Part Number A95101-01
You can use the web cache feature of Oracle9iAS to improve performance, availability, and scalability of your applications without modifying them. You just have to specify which pages in your applications you want to cache using the Oracle Web Cache Manager tool.
This guide does not cover how web cache works. For an overview and details of web cache, see the Oracle9iAS Web Cache Administration and Deployment Guide.
Pages that you should cache include the following:
You use the Oracle Web Cache Manager to manage cached pages. This applies to static and dynamic elements. To cache a page, you specify the page's URL in the Oracle Web Cache Manager. You can use regular expressions to match multiple URLs and to ensure your pattern matches exactly.
The next section shows how the Employee Benefit application caches a combination of static pages and dynamic pages.
The only static element in the Employee Benefit application is a style sheet (blaf.css).
The ID page (Figure 2-1), which prompts the user to enter an employee ID, is a static page in the sense that it does not change from user to user, but it is generated dynamically. This is a good page to cache.
The most requested pages in the application are the pages that display employee information. Caching these pages would improve application performance. These pages are dynamically generated, however; the application needs to invalidate them when they are no longer valid.
There are no graphics to cache in this application.
Figure 8-1 shows the Oracle Web Cache Manager with the Cacheability Rules page selected. The first three lines are specific to the Employee Benefit application.
The ID page and the pages that display employee information have similar URLs. The URL for the ID page is:
The employee information pages have URLs that look something like this:
Both URLs have
action=queryEmployee. The following regular expression covers both URLs:
To cache the style sheet, specify its URL in the Oracle Web Cache Manager. The ^ and $ are special characters used in regular expressions to indicate the beginning and the end of a line. This ensures that the pattern matches exactly.
The second rule, which matches
^/empbft/$, specifies an optional convenience page that provides a link to the ID page of the application. This page is static. If you have a page external to the application that links to the application, then you do not need this page and URL.
You need to invalidate dynamic pages in the cache when they are no longer valid. To invalidate cached pages, send an XML file with the URL of the pages that you want to invalidate to web cache.
The Employee Benefit application caches the employee information page, which should be invalidated as soon as the data in the database is updated. One way to do this is to send an invalidation message to web cache at the end of the add and remove benefit operations. This method, however, does not invalidate the pages when other applications update the underlying tables in the database that the Employee Benefit application uses.
A better way is to have the database send the invalidation message when the data in the tables changes. To do this, set up triggers on the tables to fire when data in the tables gets updated. The triggers can call a procedure to send the invalidation message to web cache.
The procedure that the triggers invoke looks like the following:
-- Usage: -- SQL> set serveroutput on (When debugging to see dbms_output.put_line's) -- SQL> exec invalidate_emp('doliu-sun',4001,122); -- create or replace procedure invalidate_emp ( machine in varchar2, port in integer, emp in integer) is d integer; c utl_tcp.connection; -- TCP/IP connection to the Web server DQUOTE constant varchar2(1) := chr(34); CR constant varchar2(1) := chr(13); AMP constant varchar2(1) := chr(38); uri varchar2(100) := '/empbft/controller?action=queryEmployee' || AMP || 'amp;empID=' || emp; content_length integer; BEGIN -- Note: The 177 + Length of uri to invalidate = Content-Length content_length := LENGTH(uri) + 177; dbms_output.put_line('Content-Length:' || content_length); -- -- open connection c := utl_tcp.open_connection(machine, port); -- -- Send the HTP Protocol Header -- send HTTP POST for Oracle Web Cache d := utl_tcp.write_line(c, 'POST /x-oracle-cache-invalidate HTTP/1.0'); -- -- Note: The Authorization passes the User:Password as a base64 encoded -- string. ie. invalidator:admin => d := utl_tcp.write_line(c, 'Authorization: BASIC aW52YWxpZGF0b3I6YWRtaW4='); d := utl_tcp.write_line(c, 'Content-Length: ' || content_length); dbms_output.put_line('Content-Length: ' || content_length); -- -- send TWO CR's per HTTP Protocol (Note: One from above) -- (Note: If testing with telnet count cr as 2 characters) d := utl_tcp.write_line(c, CR ); -- -- send Calypso xml Invalidation File d := utl_tcp.write_line(c, '<?xml version=' || DQUOTE || '1.0' || DQUOTE || '?>'); d := utl_tcp.write_line(c, '<!DOCTYPE INVALIDATION SYSTEM ' || DQUOTE || 'internal:///invalidation.dtd' || DQUOTE || '>'); d := utl_tcp.write_line(c, '<INVALIDATION>'); -- -- May need to uncomment this for testing dif. expressions. -- d := utl_tcp.write_line(c, '<URL EXP=' || DQUOTE || '/cache.htm' || DQUOTE -- || ' PREFIX=' || DQUOTE || 'NO' || DQUOTE || '>'); d := utl_tcp.write_line(c, '<URL EXP=' || DQUOTE || uri || DQUOTE || ' PREFIX=' || DQUOTE || 'NO' || DQUOTE || '>'); -- d := utl_tcp.write_line(c, '<VALIDITY LEVEL=' || DQUOTE || '0' || DQUOTE || ' />'); d := utl_tcp.write_line(c, '</URL>'); d := utl_tcp.write_line(c, '</INVALIDATION>'); -- BEGIN LOOP -- Capture some of the expected return output when debugging dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),1,80)); -- read result dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),81,160)); dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),161,240)); dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),241,320)); dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),321,400)); dbms_output.put_line(substr(utl_tcp.get_line(c, TRUE),401,480)); END LOOP; EXCEPTION WHEN utl_tcp.end_of_input THEN NULL; -- end of input END; utl_tcp.close_connection(c); END;
The invalidate message that the procedure sends to web cache is an XML file. The file looks like the following:
<?xml version="1.0"?> <!DOCTYPE INVALIDATION SYSTEM "internal:///invalidation.dtd"> <INVALIDATION> <URL EXP="uri" PREFIX="NO"> <VALIDITY LEVEL="0" /> </URL> </INVALIDATION>
The uri is replaced with something like:
Web cache listens on a specific port. The procedure calls utl_tcp.open_connection to open a connection to web cache and sends an HTTP header:
POST /x-oracle-cache-invalidate HTTP/1.0 Authorization: BASIC aW52YWxpZGF0b3I6YWRtaW4= Content-Length: contentLength
Note that the procedure has to calculate the content length. It starts with 177, which is the length of the XML file, to which it adds the length of the uri.
The Authorization specifies the username and password for web cache.
The underlying tables in the database have the following triggers. These triggers run the invalidate procedure.
The first trigger is fired when a row is deleted from the employee_benefit_items table.
CREATE OR REPLACE TRIGGER AFTER_DEL_TRIG AFTER DELETE on employee_benefit_items FOR EACH ROW BEGIN invalidate_emp('doliu-sun', 4001, :old.EMPLOYEE_ID); END;
The second trigger is fired when a row is inserted or updated in the employee_benefit_items table.