Previous Contents Index Next |
Sun Java System Application Server Standard and Enterprise Edition 7 2004Q2 Developer's Guide to Web Applications

> ## Chapter 2
> Using Servlets

> This chapter describes how to create effective servlets to control application interactions running on a Sun Java System Application Server, including standard servlets. In addition, this chapter describes the Sun Java System Application Server features to use to augment the standards.

> This chapter contains the following sections:

> - About Servlets
> - Creating Servlets
> - Invoking Servlets
> - Servlet Output
> - Caching Servlet Results
> - About the Servlet Engine

> ##

> About Servlets

> Servlets, like applets, are reusable Java applications. However, servlets run on an application server or web server rather than in a web browser.

> Servlets supported by the Sun Java System Application Server are based on the Java Servlet Specification v2.3. All relevant specifications are accessible from install_dir/docs/index.htm, where install_dir is the directory where the Sun Java System Application Server is installed.

> Servlets are used for an application’s presentation logic. A servlet acts as an application’s central dispatcher by processing form input, invoking business logic components encapsulated in EJB components, and formatting web page output using JSPs. Servlets control the application flow from one user interaction to the next by generating content in response to user requests.

> The fundamental characteristics are:

> - Servlets are created and managed at runtime by the Sun Java System Application Server servlet engine.
> - Servlets operate on input data that is encapsulated in a request object.
> - Servlets respond to a query with data encapsulated in a response object.
> - Servlets call EJB components to perform business logic functions.
> - Servlets call JSPs to perform page layout functions.
> - Servlets are extensible; use the APIs provided with the Sun Java System Application Server to add functionality.
> - Servlets provide user session information persistence between interactions.
> - Servlets can be part of an application or they can reside discretely on the application server so they are available to multiple applications.
> - Servlets can be dynamically reloaded while the server is running.
> - Servlets are addressable with URLs; buttons on an application’s pages often point to servlets.
> - Servlets can call other servlets.

> ### Servlet Data Flow

> When a user clicks a Submit button, information entered in a display page is sent to a servlet. The servlet processes the incoming data and orchestrates a response by generating content, often through business logic components, which are EJB components. Once the content is generated, the servlet creates a response page, usually by forwarding the content to a JSP. The response is sent back to the client, which sets up the next user interaction.

> The following illustration shows the information flow to and from the servlet.

> Figure 2-1 Servlet Data Flow Steps

> The steps are as follows:

> 1. Servlet processes the client request
> 2. Servlet generates content
> 3. Servlet creates response and either:
> 1. Sends it back directly to the client

> or

> 2. Dispatches the task to a JSP

> The servlet remains in memory, available to process another request.

> ### Servlet Types

> There are two main servlet types:

> - Generic servlets
> - Extend javax.servlet.GenericServlet.
> - Are protocol independent; they contain no inherent HTTP support or any other transport protocol.
> - HTTP servlets
> - Extend javax.servlet.HttpServlet.
> - Have built-in HTTP protocol support and are more useful in a Sun Java System Application Server environment.

> For both servlet types, implement the constructor method init() and the destructor method destroy() to initialize or deallocate resources, respectively.

> All servlets must implement a service() method, which is responsible for handling servlet requests. For generic servlets, simply override the service method to provide routines for handling requests. HTTP servlets provide a service method that automatically routes the request to another method in the servlet based on which HTTP transfer method is used. So, for HTTP servlets, override doPost() to process POST requests, doGet() to process GET requests, and so on.

> ##

> Creating Servlets

> To create a servlet, perform the following tasks:

> - Design the servlet into your application, or, if accessed in a generic way, design it to access no application data.
> - Create a class that extends either GenericServlet or HttpServlet, overriding the appropriate methods so it handles requests.
> - Use the Sun Java System Application Server Administration interface to create a web application deployment descriptor. For details, see Chapter 6, “Assembling and Deploying Web Modules.”

> The rest of this section discusses the following topics:

> - Creating the Class Declaration
> - Overriding Methods
> - Accessing Parameters and Storing Data
> - Handling Sessions and Security
> - Accessing Business Logic Components
> - Handling Threading Issues
> - Delivering Client Results

> ### Creating the Class Declaration

> To create a servlet, write a public Java class that includes basic I/O support as well as the package javax.servlet. The class must extend either GenericServlet or HttpServlet. Since Sun Java System Application Server servlets exist in an HTTP environment, you should extend HttpServlet. If the servlet is part of a package, you must also declare the package name so the class loader can properly locate it.

> The following example header shows the HTTP servlet declaration called myServlet:

> import java.io.*;
> import javax.servlet.*;
> import javax.servlet.http.*;
> public class myServlet extends HttpServlet {
> ...servlet methods...
> }

> ### Overriding Methods

> Next, override one or more methods to provide servlet instructions to perform its intended task. All processing by a servlet is done on a request-by-request basis and happens in the service methods, either service() for generic servlets or one of the do Operation() methods for HTTP servlets. This method accepts incoming requests, processing them according to the instructions you provide, and directs the output appropriately. You can create other methods in a servlet as well.

> Business logic may involve database access to perform a transaction or passing the request to an EJB component.

> #### Overriding Initialize

> Override the class initializer init() to initialize or allocate resources for the servlet instance’s life, such as a counter. The init() method runs after the servlet is instantiated but before it accepts any requests. For more information, see the servlet API specification.

> Note | All init() methods must call super.init(ServletConfig) to set their scope. This makes the servlet’s configuration object available to other servlet methods. If this call is omitted, a 500 SC_INTERNAL_SERVER_ERROR appears in the browser when the servlet starts up.

> Note | A web application is not started if any of its components, such as a filter, throws a ServletException during initialization. This is to ensure that if any part of the web application runs, all of it runs. It is especially important that a web application fail if security components fail.

> The following example of the init() method initializes a counter by creating a public integer variable called thisMany:

> public class myServlet extends HttpServlet {
> int thisMany;
> public void init (ServletConfig config) throws ServletException
> {
> super.init(config);
> thisMany = 0;
> }
> }

> Now other servlet methods can access the variable.

> #### Overriding Destroy

> Override the class destructor destroy() to write log messages or to release resources that have been opened in the servlet’s life cycle. Resources should be appropriately closed and dereferenced so that they are recycled or garbage collected. The destroy() method runs just before the servlet itself is deallocated from memory. For more information, see the servlet API specification.

> For example, the destroy() method could write a log message like the following, based on the example for Overriding Initialize above:

> out.println("myServlet was accessed " + thisMany " times.\n");

> #### Overriding Service, Get, and Post

> When a request is made, the Sun Java System Application Server hands the incoming data to the servlet engine to process the request. The request includes form data, cookies, session information, and URL name-value pairs, all in a type HttpServletRequest object called the request object. Client metadata is encapsulated as a type HttpServletResponse object called the response object. The servlet engine passes both objects as the servlet’s service() method parameters.

> The default service() method in an HTTP servlet routes the request to another method based on the HTTP transfer method (POST, GET, and so on). For example, HTTP POST requests are routed to the doPost() method, HTTP GET requests are routed to the doGet() method, and so on. This enables the servlet to perform different request data processing depending on the transfer method. Since the routing takes place in service(), there is no need to generally override service() in an HTTP servlet. Instead, override doGet(), doPost(), and so on, depending on the expected request type.

> The automatic routing in an HTTP servlet is based simply on a call to request.getMethod(), which provides the HTTP transfer method. In a Sun Java System Application Server, request data is already preprocessed into a name-value list by the time the servlet sees the data, so simply overriding the service() method in an HTTP servlet does not lose any functionality. However, this does make the servlet less portable, since it is now dependent on preprocessed request data.

> Override the service() method (for generic servlets) or the doGet() or doPost() methods (for HTTP servlets) to perform tasks needed to answer the request. Very often, this means accessing EJB components to perform business transactions, collating the needed information (in the request object or in a JDBC result set object), and then passing the newly generated content to a JSP for formatting and delivery back to the client.

> Most operations that involve forms use either a GET or a POST operation, so for most servlets you override either doGet() or doPost(). Note that implementing both methods to provide for both input types or simply pass the request object to a central processing method.

> For example:

> public void doGet (HttpServletRequest request,
> HttpServletResponse response)
> throws ServletException, IOException {
> doPost(request, response);
> }

> All request-by-request traffic in an HTTP servlet is handled in the appropriate do Operation() method, including session management, user authentication, dispatching EJB components and JSPs, and accessing Sun Java System Application Server features.

> If a servlet intends to call the RequestDispatcher method include() or forward(), be aware the request information is no longer sent as HTTP POST, GET, and so on. In other words, if a servlet overrides doPost(), it may not process anything if another servlet calls it, if the calling servlet happens to receive its data through HTTP GET. For this reason, be sure to implement routines for all possible input types, as explained above. RequestDispatcher methods always call service().

> For more information, see Calling a Servlet Programmatically.

> Note | Arbitrary binary data, such as uploaded files or images, can be problematic, since the web connector translates incoming data into name-value pairs by default. You can program the web connector to properly handle these kinds of data and package them correctly in the request object.

> ### Accessing Parameters and Storing Data

> Incoming data is encapsulated in a request object. For HTTP servlets, the request object type is HttpServletRequest. For generic servlets, the request object type is ServletRequest. The request object contains all request parameters, including your own request values called attributes.

> To access all incoming request parameters, use the getParameter() method. For example:

> String username = request.getParameter("username");

> Set and retrieve values in a request object using setAttribute() and getAttribute(), respectively. For example:

> request.setAttribute("favoriteDwarf", "Dwalin");

> This shows one way to transfer data to a JSP, since JSPs have access to the request object as an implicit bean.

> ### Handling Sessions and Security

> From a web or application server’s perspective, a web application is a series of unrelated server hits. There is no automatic recognition if a user has visited the site before, even if their last interaction were seconds before. A session provides a context between multiple user interactions by remembering the application state. Clients identify themselves during each interaction by a cookie, or, in the case of a cookie-less browser, by placing the session identifier in the URL.

> A session object can store objects, such as tabular data, information about the application’s current state, and information about the current user. Objects bound to a session are available to other components that use the same session.

> For more information, see Chapter 4, “Creating and Managing User Sessions.”

> After a successful login, you should direct a servlet to establish the user’s identity in a standard object called a session object that holds information about the current session, including the user’s login name and whatever additional information to retain. Application components can then query the session object to obtain user authentication.

> To provide a secure user session for your application, see Chapter 5, “Securing Web Applications.”

> ### Accessing Business Logic Components

> In the Sun Java System Application Server programming model, you implement business logic, including database or directory transactions and complex calculations, in EJB components. A request object reference can be passed as an EJB parameter to perform the specified task.

> Store the results from database transactions in JDBC ResultSet objects and pass object references to other components for formatting and delivery to the client. Also, store request object results by using the request.setAttribute() method, or in the session by using the session.setAttribute() method. Objects stored in the request object are valid only for the request length, or in other words for this particular servlet thread. Objects stored in the session persist for the session duration, which can span many user interactions.

> This example shows a servlet accessing an EJB component called ShoppingCart. The servlet creates a cart handle by casting the user’s session ID as a cart after importing the cart’s remote interface. The cart is stored in the user’s session.

> import cart.ShoppingCart;
> // Get the user's session and shopping cart
> HttpSession session = request.getSession(true);
> ShoppingCart cart =
> (ShoppingCart)session.getAttribute(session.getId());
> // If the user has no cart, create a new one
> if (cart == null) {
> String jndiNm = "java:comp/env/ejb/ShoppingCart";
> javax.naming.Context initCtx = null;
> Object home = null;
> try {
> initCtx = new javax.naming.InitialContext(env);
> java.util.Properties props = null;
> home = initCtx.lookup(jndiNm);
> cart = ((IShoppingCartHome) home).create();
> session.setValue(session.getId(),cart);
> }
> catch (Exception ex) {
> .....
> .....
> }
> }

> Access EJB components from servlets by using the Java Naming and Directory Interface™ (JNDI) to establish a handle, or proxy, to the EJB component. Next, refer to the EJB component as a regular object; overhead is managed by the bean’s container.

> This example shows JNDI looking up a proxy for the shopping cart:

> String jndiNm = "java:comp/env/ejb/ShoppingCart";
> javax.naming.Context initCtx;
> Object home;
> try
> {
> initCtx = new javax.naming.InitialContext(env);
> }
> catch (Exception ex)
> {
> return null;
> }
> try
> {
> java.util.Properties props = null;
> home = initCtx.lookup(jndiNm);
> }
> catch(javax.naming.NameNotFoundException e)
> {
> return null;
> }
> catch(javax.naming.NamingException e)
> {
> return null;
> }
> try
> {
> IShoppingCart cart = ((IShoppingCartHome) home).create();
> }
> catch (...) {...}

> For more information on EJB components, see the Sun Java System Application Server Developer’s Guide to Enterprise JavaBeans Technology.

> Note | To avoid collisions with names of other enterprise resources in JNDI, and to avoid portability problems, all names in a Sun Java System Application Server application should begin with the string java:comp/env.

> ### Handling Threading Issues

> By default, servlets are not thread-safe. The methods in a single servlet instance are usually executed numerous times simultaneously (up to the available memory limit). Each execution occurs in a different thread though only one servlet copy exists in the servlet engine.

> This is efficient system resource usage, but is dangerous because of how Java manages memory. Because variables belonging to the servlet class are passed by reference, different threads can overwrite the same memory space as a side effect. To make a servlet (or a block within a servlet) thread-safe, do one of the following:

> - Synchronize write access to all instance variables, as in public synchronized void method() (whole method) or synchronized(this) {...} (block only). Because synchronizing slows response time considerably, synchronize only blocks, or make sure that the blocks in the servlet do not need synchronization.

> For example, this servlet has a thread-safe block in doGet() and a thread-safe method called mySafeMethod():

> import java.io.*;
> import javax.servlet.*;
> import javax.servlet.http.*;
> public class myServlet extends HttpServlet {
> public void doGet (HttpServletRequest request,
> HttpServletResponse response)
> throws ServletException, IOException {
> //pre-processing
> synchronized (this) {
> //code in this block is thread-safe
> }
> //other processing;
> }
> public synchronized int mySafeMethod (HttpServletRequest request)
> {
> //everything that happens in this method is thread-safe
> }
> }

> - Use the SingleThreadModel class to create a single-threaded servlet. When a single-threaded servlet is deployed to the Sun Java System Application Server, the servlet engine creates a servlet instance pool used for incoming requests (multiple copies of the same servlet in memory). You can change the number of servlet instances in the pool by setting the singleThreadedServletPoolSize property in the Sun Java System Application Server specific web application deployment descriptor. For more information on the Sun Java System Application Server web application deployment descriptor, see Chapter 6, “Assembling and Deploying Web Modules.” A single-threaded servlet is slower under load because new requests must wait for a free instance in order to proceed, but this is not a problem with distributed, load-balanced applications since the load automatically shifts to a less busy process.

> For example, this servlet is completely single-threaded:

> import java.io.*;
> import javax.servlet.*;
> import javax.servlet.http.*;
> public class myServlet extends HttpServlet
> implements SingleThreadModel {
> servlet methods...
> }

> ### Delivering Client Results

> The final user interaction activity is to provide a response page to the client. The response page can be delivered in two ways:

> - Creating a Servlet Response Page
> - Creating a JSP Response Page

> #### Creating a Servlet Response Page

> Generate the output page within a servlet by writing to the output stream. The best way to do this depends on the output type.

> Always specify the output MIME type using setContentType() before any output commences, as in this example:

> response.setContentType("text/html");

> For textual output, such as plain HTML, create a PrintWriter object and then write to it using println. For example:

> PrintWriter output = response.getWriter();
> output.println("Hello, World\n");

> For binary output, write to the output stream directly by creating a ServletOutputStream object and then write to it using print(). For example:

> ServletOutputStream output = response.getOutputStream();
> output.print(binary_data);

> #### Creating a JSP Response Page

> Servlets can invoke JSPs in two ways:

> - The include() method in the RequestDispatcher interface calls a JSP and waits for it to return before continuing to process the interaction. The include() method can be called multiple times within a given servlet.

> This example shows a JSP using include():

> RequestDispatcher dispatcher =
> getServletContext().getRequestDispatcher("JSP_URI");
> dispatcher.include(request, response);
> ... //processing continues

> - The forward() method in the RequestDispatcher interface hands the JSP interaction control. The servlet is no longer involved with the current interaction’s output after invoking forward(), thus only one call to the forward() method can be made in a particular servlet.

> Note | You cannot use the forward() method if you have already defined a PrintWriter or ServletOutputStream object.

> This example shows a JSP using forward():

> RequestDispatcher dispatcher =
> getServletContext().getRequestDispatcher("JSP_URI");
> dispatcher.forward(request, response);

> Note | Identify which JSP to call by specifying a Universal Resource Identifier (URI). The path is a String describing a path within the ServletContext scope. There is also a getRequestDispatcher() method in the request object that takes a String argument indicating a complete path. For more information about this method, see the Java Servlet Specification, v2.3, section 8.

> For more information about JSPs, see Chapter 3, “Using JavaServer Pages.”

> ##

> Invoking Servlets

> You can invoke a servlet by directly addressing it from an application page with a URL or calling it programmatically from an already running servlet. See the following sections:

> - Calling a Servlet with a URL
> - Calling a Servlet Programmatically

> ### Calling a Servlet with a URL

> You can call servlets by using URLs embedded as links in an application’s HTML or JSP pages. The format of these URLs is as follows:

> http://server:port/context_root/servlet/servlet_name?name=value

> The following table describes each URL section.

> Table 2-1 URL Fields for Servlets Within an Application

> URL element | Description
> --- | ---
> server:port | The IP address (or host name) and optional port number. To access the default web module for a virtual server, specify only this URL section. You do not need to specify the context_root or servlet_name unless you also wish to specify name-value parameters.
> context_root | For an application, the context root is defined in the context-root element of the application.xml or sun-application.xml file. For an individually deployed web module, you specify the context root during deployment.
> servlet | Only needed if no servlet-mapping is defined in the web.xml file.
> servlet_name | The servlet-name (or servlet-mapping if defined) as configured in the web.xml file.
> ?name=value... | Optional servlet name-value parameters.

> In this example, sun is the host name, MortPages is the context root, and calcMortgage is the servlet name:

> http://www.sun.com/MortPages/servlet/calcMortgage?rate=8.0&per=360&bal=180000

> ### Calling a Servlet Programmatically

> First, identify which servlet to call by specifying a URI. This is normally a path relative to the current application. For example, if your servlet is part of an application with a context root called OfficeFrontEnd, the URL to a servlet called ShowSupplies from a browser is as follows:

> http://server:port/OfficeApp/OfficeFrontEnd/servlet/ShowSupplies?name=value

> You can call this servlet programmatically from another servlet in one of two ways, as described below.

> - To include another servlet’s output, use the include() method from the RequestDispatcher interface. This method calls a servlet by its URI and waits for it to return before continuing to process the interaction. The include() method can be called multiple times within a given servlet.

> For example:

> RequestDispatcher dispatcher =
> getServletContext().getRequestDispatcher("/ShowSupplies");
> dispatcher.include(request, response);

> - To hand interaction control to another servlet, use the RequestDispatcher interface’s forward() method with the servlet’s URI as a parameter.

> Note | Forwarding a request means the original servlet is no longer involved with the current interaction output after forward() is invoked. Therefore, only one forward() call can be made in a particular servlet.

> This example shows a servlet using forward():

> RequestDispatcher dispatcher =
> getServletContext().getRequestDispatcher("/ShowSupplies");
> dispatcher.forward(request, response);

> ##

> Servlet Output

> ServletContext.log messages are sent to the server log.

> By default, the System.out and System.err output of servlets are sent to the server log, and during start-up server log messages are echoed to the System.err output. You can change these defaults in these ways:

> - Using the Administration Interface
> - Editing the server.xml File

> ### Using the Administration Interface

> Use the Administration interface as follows:

> 1. Click on the Logging tab of the server instance page in the Administration interface.
> 2. Check or uncheck these boxes:
> - Log stdout content to event log - If true, System.out output is sent to the server log.
> - Log stderr content to event log - If true, System.err output is sent to the server log.
> - Echo to stderr - If true, server log messages are echoed System.err.
> 3. Click on the Save button.
> 4. Go to the server instance page and select the Apply Changes button.

> For more information, see the Sun Java System Application Server Administrator’s Guide.

> ### Editing the server.xml File

> Edit the server.xml file as follows, then restart the server:

> <log-service log-stdout=false
> log-stderr=false
> echo-log-messages-to-stderr=false

> For more information about server.xml, see the Sun Java System Application Server Administrator’s Configuration File Reference.

> ##

> Caching Servlet Results

> The Sun Java System Application Server can cache the results of invoking a servlet, a JSP, or any URL pattern to make subsequent invocations of the same servlet, JSP, or URL pattern faster. The Sun Java System Application Server caches the request results for a specific amount of time. In this way, if another data call occurs, the Sun Java System Application Server can return the cached data instead of performing the operation again. For example, if your servlet returns a stock quote that updates every 5 minutes, you set the cache to expire after 300 seconds.

> Whether to cache results and how to cache them depends on the data involved. For example, it makes no sense to cache the results of a quiz submission, because the input to the servlet is different each time. However, you could cache a high level report showing demographic data taken from quiz results that is updated once an hour.

> You can define how a Sun Java System Application Server web application handles response caching by editing specific fields in the sun-web.xml file. In this way, you can create programmatically standard servlets that still take advantage of this valuable Sun Java System Application Server feature.

> For more information about JSP caching, see “JSP Caching” on page 58.

> Note | For information about caching static file content, see the nsfc.conf file, described in the Sun Java System Application Server Administrator’s Configuration File Reference.

> The rest of this section covers the following topics:

> - Caching Features
> - Default Cache Configuration
> - Caching Example
> - CacheHelper Interface
> - CacheKeyGenerator Interface

> ### Caching Features

> Sun Java System Application Server 7 has the following web application response caching capabilities:

> - Caching is configurable based on the servlet name or the URI.
> - When caching is based on the URI, this includes user specified parameters in the query string. For example, a response from /garden/catalog?category=roses is different from a response from /garden/catalog?category=lilies. These responses are stored under different keys in the cache.
> - Cache size, entry timeout, and other caching behaviors are configurable.
> - Entry timeout is measured from the time an entry is created or refreshed. You can override this timeout for an individual cache mapping by specifying the cache-mapping subelement timeout.
> - You can determine caching criteria programmatically by writing a cache helper class. For example, if a servlet only knows when a back end data source was last modified, you can write a helper class to retrieve the last modified timestamp from the data source and decide whether to cache the response based on that timestamp. See CacheHelper Interface.
> - You can determine cache key generation programmatically by writing a cache key generator class. See CacheKeyGenerator Interface.
> - All non-ASCII request parameter values specified in cache key elements must be URL encoded. The caching subsystem attempts to match the raw parameter values in the request query string.
> - Since newly updated classes impact what gets cached, the web container clears the cache during dynamic deployment or reloading of classes.
> - The following HttpServletRequest request attributes are exposed:
> - com.sun.appserv.web.cachedServletName, the cached servlet target
> - com.sun.appserv.web.cachedURLPattern, the URL pattern being cached

> ### Default Cache Configuration

> If you enable caching but do not provide any special configuration for a servlet or JSP, the default cache configuration is as follows:

> - The default cache timeout is 30 seconds.
> - Only the HTTP GET method is eligible for caching.
> - HTTP requests with cookies or sessions automatically disable caching.
> - No special consideration is given to Pragma:, Cache-control:, or Vary: headers.
> - The default key consists of the Servlet Path (minus pathInfo and the query string).
> - A “least recently used” list is maintained to evict cache entries if the maximum cache size is exceeded.
> - Key generation concatenates the servlet path with key field values, if any are specified.

> ### Caching Example

> Here is an example cache element in the sun-web.xml file:

> <cache max-capacity="8192" timeout="60">
> <cache-helper name="myHelper" class-name="MyCacheHelper"/>
> <cache-mapping>
> <servlet-name>myservlet</servlet name
> <timeout name="timefield">120</timeout>
> <http-method>GET</http-method>
> <http-method>POST</http-method>
> </cache-mapping>
> <cache-mapping>
> <url-pattern> /catalog/* </url-pattern>
> <!-- cache the best selling category; cache the responses to
> -- this resource only when the given parameters exist. cache
> -- only when the catalog parameter has 'lilies' or 'roses'
> -- but no other catalog varieties:
> -- /orchard/catalog?best&category='lilies'
> -- /orchard/catalog?best&category='roses'
> -- but not the result of
> -- /orchard/catalog?best&category='wild'
> -->
> <constraint-field name='best' scope='request.parameter'/>
> <constraint-field name='category' scope='request.parameter'>
> <value> roses </value>
> <value> lilies </value>
> </constraint-field>
> <!-- Specify that a particular field is of given range but the
> -- field doesn't need to be present in all the requests -->
> <constraint-field name='SKUnum' scope='request.parameter'>
> <value match-expr='in-range'> 1000 - 2000 </value>
> </constraint-field>
> <!-- cache when the category matches with any value other than
> -- a specific value -->
> <constraint-field name="category" scope="request.parameter>
> <value match-expr="equals" cache-on-match-failure="true">bogus</value>
> </constraint-field>
> </cache-mapping>
> <cache-mapping>
> <servlet-name> InfoServlet </servlet name>
> <cache-helper-ref>myHelper</cache-helper-ref>
> </cache-mapping>
> </cache>

> For more information about the sun-web.xml caching settings, see “Caching Elements” on page 119.

> ### CacheHelper Interface

> Here is the CacheHelper interface:

> package com.sun.appserv.web.cache;
> import java.util.Map
> import javax.servlet.ServletContext;
> import javax.servlet.http.HttpServletRequest;
> /** CacheHelper interface is an user-extensible interface to customize:
> * a) the key generation b) whether to cache the response.
> */
> public interface CacheHelper {
> // name of request attributes
> public static final String ATTR_CACHE_MAPPED_SERVLET_NAME =
> "com.sun.appserv.web.cachedServletName";
> public static final String ATTR_CACHE_MAPPED_URL_PATTERN =
> "com.sun.appserv.web.cachedURLPattern";
> public static final int TIMEOUT_VALUE_NOT_SET = -2;
> /** initialize the helper
> * @param context the web application context this helper belongs to
> * @exception Exception if a startup error occurs
> */
> public void init(ServletContext context, Map props) throws Exception;
> /** getCacheKey: generate the key to be used to cache this request
> * @param request incoming <code>HttpServletRequest</code> object
> * @returns the generated key for this requested cacheable resource.
> */
> public String getCacheKey(HttpServletRequest request);
> /** isCacheable: is the response to given request cachebale?
> * @param request incoming <code>HttpServletRequest</code> object
> * @returns <code>true</code> if the response could be cached. or
> * <code>false</code> if the results of this request must not be cached.
> */
> public boolean isCacheable(HttpServletRequest request);
> /** isRefreshNeeded: is the response to given request be refreshed?
> * @param request incoming <code>HttpServletRequest</code> object
> * @returns <code>true</code> if the response needs to be refreshed.
> * or return <code>false</code> if the results of this request
> * don't need to be refreshed.
> */
> public boolean isRefreshNeeded(HttpServletRequest request);
> /** get timeout for the cached response.
> * @param request incoming <code>HttpServletRequest</code> object
> * @returns the timeout in seconds for the cached response; a return
> * value of -1 means the response never expires and a value of -2 indicates
> * helper cannot determine the timeout (container assigns default timeout)
> */
> public int getTimeout(HttpServletRequest request);
> /**
> * Stop the helper from active use
> * @exception Exception if an error occurs
> */
> public void destroy() throws Exception;
> }

> ### CacheKeyGenerator Interface

> The built-in default CacheHelper implementation allows web applications to customize the key generation. An application component (in a servlet or JSP) can set up a custom CacheKeyGenerator implementation as an attribute in the ServletContext.

> The name of the context attribute is configurable as the value of the cacheKeyGeneratorAttrName property in the default-helper element of the sun-web.xml deployment descriptor. For more information, see “default-helper” on page 122.

> Here is the CacheKeyGenerator interface:

> package com.sun.appserv.web.cache;
> import javax.servlet.ServletContext;
> import javax.servlet.http.HttpServletRequest;
> /** CacheKeyGenerator: a helper interface to generate the key that
> * is used to cache this request.
> *
> * Name of the ServletContext attribute implementing the
> * CacheKeyGenerator is configurable via a property of the
> * default-helper in sun-web.xml:
> * <default-helper>
> * <property
> * name="cacheKeyGeneratorAttrName"
> * value="com.acme.web.MyCacheKeyGenerator" />
> * </default-helper>
> *
> * Caching engine looks up the specified attribute in the servlet
> * context; the result of the lookup must be an implementation of the
> * CacheKeyGenerator interface.
> */
> public interface CacheKeyGenerator {
> /** getCacheKey: generate the key to be used to cache the
> * response.
> * @param context the web application context
> * @param request incoming <code>HttpServletRequest</code>
> * @returns key string used to access the cache entry.
> * if the return value is null, a default key is used.
> */
> public String getCacheKey(ServletContext context,
> HttpServletRequest request);
> }

> ##

> About the Servlet Engine

> Servlets exist in and are managed by the servlet engine in the Sun Java System Application Server. The servlet engine is an internal object that handles all servlet meta functions. These functions include instantiation, initialization, destruction, access from other components, and configuration management.

> ### Instantiating and Removing Servlets

> After the servlet engine instantiates the servlet, the servlet engine runs its init() method to perform any necessary initialization. Override this method to perform an initialize a function for the servlet’s life, such as initializing a counter.

> When a servlet is removed from service, the server engine calls the destroy() method in the servlet so that the servlet can perform any final tasks and deallocate resources. Override this method to write log messages or clean up any lingering connections that won’t be caught in garbage collection.

> ### Request Handling

> When a request is made, the Sun Java System Application Server hands the incoming data to the servlet engine. The servlet engine processes the request’s input data, such as form data, cookies, session information, and URL name-value pairs, into an HttpServletRequest request object type.

> The servlet engine also creates an HttpServletResponse response object type. The engine then passes both as parameters to the servlet’s service() method.

> In an HTTP servlet, the default service() method routes requests to another method based on an HTTP transfer method, such as POST, GET, and so on. For example, HTTP POST requests are sent to the doPost() method, HTTP GET requests are sent to the doGet() method, and so on. This enables the servlet to process request data differently, depending on which transfer method is used. Since the routing takes place in the service method, you generally do not override service() in an HTTP servlet. Instead, override doGet(), doPost(), and so on, depending on the request type you expect.

> Tip | To enable automatic routing in an HTTP servlet, call request.getMethod(), which provides the HTTP transfer method. Since request data is already preprocessed into a name value list in the Sun Java System Application Server, you could simply override the service() method in an HTTP servlet without losing functionality. However, this does make the servlet less portable, since it is now dependent on preprocessed request data.

> To perform the tasks to answer a request, override the service() method for generic servlets, and the doGet() or doPost() methods for HTTP servlets. Very often, this means accessing EJB components to perform business transactions, collating the information in the request object or in a JDBC ResultSet object, and then passing the newly generated content to a JSP for formatting and delivery back to the user.

> ### Allocating Servlet Engine Resources

> By default, the servlet engine creates a thread for each new request. This is less resource intensive than instantiating a new servlet copy in memory for each request. Avoid threading issues, since each thread operates in the same memory space where servlet object variables can overwrite each other.

> If a servlet is specifically written as a single thread, the servlet engine creates a pool of servlet instances to be used for incoming requests. If a request arrives when all instances are busy, it is queued until an instance becomes available. The number of pool instances is configurable in the sun-web.xml file, in the singleThreadedServletPoolSize property of the sun-web-app element.

> For more information about the sun-web.xml file, see Chapter 6, “Assembling and Deploying Web Modules.” For more information on threading issues, see Handling Threading Issues.

> Previous Contents Index Next

> Copyright 2004 Sun Microsystems, Inc. All rights reserved.