Skip navigation.
Downloads | Product Documentation | Support

Developing Web Applications, Servlets, and JSPs for WebLogic Server

# Servlet Programming Tasks

The following sections describe how to write HTTP servlets in a WebLogic Server environment:

- Initializing a Servlet
- Providing an HTTP Response
- Retrieving Client Input
- Using Cookies in a Servlet
- Response Caching
- Using WebLogic Services from an HTTP Servlet
- Accessing Databases
- Threading Issues in HTTP Servlets
- Dispatching Requests to Another Resource
- Proxying Requests to Another Web Server
- Clustering Servlets
- Referencing a Servlet in a Web Application
- URL Pattern Matching
- The SimpleApacheURLMatchMap Utility
- Avoiding Hung Threads

# Initializing a Servlet

Normally, WebLogic Server initializes a servlet when the first request is made for the servlet. Subsequently, if the servlet is modified, the `destroy()` method is called on the existing version of the servlet. Then, after a request is made for the modified servlet, the `init()` method of the modified servlet is executed. For more information, see Servlet Best Practices.

When a servlet is initialized, WebLogic Server executes the `init()` method of the servlet. Once the servlet is initialized, it is not initialized again until you restart WebLogic Server or modify the servlet code. If you choose to override the `init()` method, your servlet can perform certain tasks, such as establishing database connections, when the servlet is initialized. (See Overriding the init() Method.)

## Initializing a Servlet when WebLogic Server Starts

Rather than having WebLogic Server initialize a servlet when the first request is made for it, you can first configure WebLogic Server to initialize a servlet when the server starts. You do this by specifying the servlet class in the `load-on-startup` element in the J2EE standard Web Application deployment descriptor, web.xml. The order in which resources within a Web application are initialized is as follows:

1. ServletContextListeners—the contextCreated() callback for ServletContextListeners registered for this Web application.
2. ServletFilters init() method.
3. Servlet init() method, marked as load-on-startup in web.xml.

You can pass parameters to an HTTP servlet during initialization by defining these parameters in the Web Application containing the servlet. You can use these parameters to pass values to your servlet every time the servlet is initialized without having to rewrite the servlet.

For example, the following entries in the J2EE standard Web Application deployment descriptor, web.xml, define two initialization parameters: `greeting`, which has a value of `Welcome` and `person`, which has a value of `WebLogic Developer`.

>     <servlet>
>       ...
>      <init-Purim>
>         <description>The salutation</description>
>         <param-name>greeting</param-name>
>         <param-value>Welcome</param-value>
>       </init-param>
>      <init-param>
>         <description>name</description>
>         <param-name>person</param-name>
>         <param-value>WebLogic Developer</param-value>
>       </init-param>
>     </servlet>

To retrieve initialization parameters, call the `getInitParameter(String name)` method from the parent `javax.servlet.GenericServlet` class. When passed the name of the parameter, this method returns the parameter's value as a `String`.

## Overriding the init() Method

You can have your servlet execute tasks at initialization time by overriding the `init()` method. The following code fragment reads the `<init-param>` tags that define a greeting and a name in the J2EE standard Web Application deployment descriptor, web.xml:

>     String defaultGreeting;
>     String defaultName;

>     public void init(ServletConfig config)
>         throws ServletException {
>       if ((defaultGreeting = getInitParameter("greeting")) == null)
>         defaultGreeting = "Hello";

>       if ((defaultName = getInitParameter("person")) == null)
>         defaultName = "World";
>     }

The values of each parameter are stored in the class instance variables `defaultGreeting` and `defaultName`. The first code tests whether the parameters have null values, and if null values are returned, provides appropriate default values.

You can then use the `service()` method to include these variables in the response. For example:

>       out.print("<body><h1>");
>       out.println(defaultGreeting + " " + defaultName + "!");
>       out.println("</h1></body></html>");

The init() method of a servlet does whatever initialization work is required when WebLogic Server loads the servlet. The default init() method does all of the initial work that WebLogic Server requires, so you do not need to override it unless you have special initialization requirements. If you do override init(), first call super.init() so that the default initialization actions are done first.

# Providing an HTTP Response

This section describes how to provide a response to the client in your HTTP servlet. Deliver all responses by using the `HttpServletResponse` object that is passed as a parameter to the `service()` method of your servlet.

1. Configure the `HttpServletResponse.`

Using the `HttpServletResponse` object, you can set several servlet properties that are translated into HTTP header information:

- At a minimum, set the content type using the `setContentType()` method before you obtain the output stream to which you write the page contents. For HTML pages, set the content type to `text/html`. For example:

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

- (optional) You can also use the `setContentType()` method to set the character encoding. For example:

>     res.setContentType("text/html;ISO-88859-4");

- Set header attributes using the `setHeader()` method. For dynamic responses, it is useful to set the "`Pragma`" attribute to `no-cache`, which causes the browser to always reload the page and ensures the data is current. For example:

>     res.setHeader("Pragma", "no-cache");

2. Compose the HTML page.

The response that your servlet sends back to the client must look like regular HTTP content, essentially formatted as an HTML page.Your servlet returns an HTTP response through an output stream that you obtain using the response parameter of the `service()` method. To send an HTTP response:

1. Obtain an output stream by using the `HttpServletResponse` object and one of the methods shown in the following two examples:

- `PrintWriter out = res.getWriter();`
- `ServletOutputStream out = res.getOutputStream();`

You can use both `PrintWriter` and `ServletOutputStream` in the same servlet (or in another servlet that is included in a servlet). The output of both is written to the same buffer.

1. Write the contents of the response to the output stream using the `print()` method. You can use HTML tags in these statements. For example:

>     out.print("<html><head><title>My Servlet</title>");
>     out.print("</head><body><h1>");
>     out.print("Welcome");
>     out.print("</h1></body></html>");

Any time you print data that a user has previously supplied, BEA recommends that you remove any HTML special characters that a user might have entered. If you do not remove these characters, your Web site could be exploited by cross-site scripting. For more information, refer to Securing Client Input in Servlets.

Do not close the output stream by using the `close()` method, and avoid flushing the contents of the stream. If you do not close or flush the output stream, WebLogic Server can take advantage of persistent HTTP connections, as described in the next step.

3. Optimize the response.

By default, WebLogic Server attempts to use HTTP persistent connections whenever possible. A persistent connection attempts to reuse the same HTTP TCP/IP connection for a series of communications between client and server. Application performance improves because a new connection need not be opened for each request. Persistent connections are useful for HTML pages containing many in-line images, where each requested image would otherwise require a new TCP/IP connection.

Using the WebLogic Server Administration Console, you can configure the amount of time that WebLogic Server keeps an HTTP connection open.

WebLogic Server must know the length of the HTTP response in order to establish a persistent connection and automatically adds a `Content-Length` property to the HTTP response header. In order to determine the content length, WebLogic Server must buffer the response. However, if your servlet explicitly flushes the `ServletOutputStream`, WebLogic Server cannot determine the length of the response and therefore cannot use persistent connections. For this reason, you should avoid explicitly flushing the HTTP response in your servlets.

You may decide that, in some cases, it is better to flush the response early to display information in the client before the page has completed; for example, to display a banner advertisement while some time-consuming page content is calculated. Conversely, you may want to increase the size of the buffer used by the servlet engine to accommodate a larger response before flushing the response. You can manipulate the size of the response buffer by using the related methods of the javax.servlet.ServletResponse interface. For more information, see the Servlet 2.4 specification.

The default value of the WebLogic Server response buffer is 12K and the buffer size is internally calculated in terms of `CHUNK_SIZE` where `CHUNK_SIZE = 4088 bytes`; if the user sets 5Kb the server rounds the request up to the nearest multiple of `CHUNK_SIZE` which is 2. and the buffer is set to 8176 bytes.

# Retrieving Client Input

The HTTP servlet API provides a interface for retrieving user input from Web pages.

An HTTP request from a Web browser can contain more than the URL, such as information about the client, the browser, cookies, and user query parameters. Use query parameters to carry user input from the browser. Use the GET method appends parameters to the URL address, and the POST method includes them in the HTTP request body.

HTTP servlets need not deal with these details; information in a request is available through the `HttpServletRequest` object and can be accessed using the `request.getParameter()` method, regardless of the send method.

Read the following for more detailed information about the ways to send query parameters from the client:

- Encode the parameters directly into the URL of a link on a page. This approach uses the `GET` method for sending parameters. The parameters are appended to the URL after a `?` character. Multiple parameters are separated by a `&` character. Parameters are always specified in name=value pairs so the order in which they are listed is not important. For example, you might include the following link in a Web page, which sends the parameter `color` with the value `purple` to an HTTP servlet called `ColorServlet`:

>     <a href=
>        "http://localhost:7001/myWebApp/ColorServlet?color=purple">
>        Click Here For Purple!</a>

- Manually enter the URL, with query parameters, into the browser location field. This is equivalent to clicking the link shown in the previous example.
- Query the user for input with an HTML form. The contents of each user input field on the form are sent as query parameters when the user clicks the form's Submit button. Specify the method used by the form to send the query parameters (`POST` or `GET`) in the `<FORM>` tag using the `METHOD="GET|POST"` attribute.

Query parameters are always sent in name`=`value pairs, and are accessed through the `HttpServletRequest` object. You can obtain an `Enumeration` of all parameter names in a query, and fetch each parameter value by using its parameter name. A parameter usually has only one value, but it can also hold an array of values. Parameter values are always interpreted as `Strings`, so you may need to cast them to a more appropriate type.

The following sample from a `service()` method examines query parameter names and their values from a form. Note that `request` is the `HttpServletRequest` object.

>       Enumeration params = request.getParameterNames();
>       String paramName = null;
>       String[] paramValues = null;

>       while (params.hasMoreElements()) {
>         paramName = (String) params.nextElement();
>         paramValues = request.getParameterValues(paramName);
>         System.out.println("\nParameter name is " + paramName);
>         for (int i = 0; i < paramValues.length; i++) {
>           System.out.println(", value " + i + " is " +
>                              paramValues[i].toString());
>         }
>       }

Note: Any time you print data that a user has supplied, BEA recommends that you remove any HTML special characters that a user might have entered. If you do not remove these characters, your Web site could be exploited by cross-site scripting. For more information, refer to Securing Client Input in Servlets.

## Methods for Using the HTTP Request

This section defines the methods of the `javax.servlet.HttpServletRequest` interface that you can use to get data from the request object. You should keep the following limitations in mind:

- You cannot read request parameters using any of the `getParameter()` methods described in this section and then attempt to read the request with the `getInputStream()` method.
- You cannot read the request with `getInputStream()` and then attempt to read request parameters with one of the `getParameter()` methods.

If you attempt either of the preceding procedures, an `illegalStateException` is thrown.

You can use the following methods of javax.servlet.HttpServeletRequest to retrieve data from the request object:

  `HttpServletRequest.getMethod()`

  Allows you to determine the request method, such as `GET` or `POST`.

  `HttpServletRequest.getQueryString()`

  Allows you to access the query string. (The remainder of the requested URL, following the `?` character.)

  `HttpServletRequest.getParameter()`

  Returns the value of a parameter.

  `HttpServletRequest.getParameterNames()`

  Returns an array of parameter names.

  `HttpServletRequest.getParameterValues()`

  Returns an array of values for a parameter.

  `HttpServletRequest.getInputStream()`

  Reads the body of the request as binary data. If you call this method after reading the request parameters with `getParameter()`, `getParameterNames()`, or `getParameterValues()`, an `illegalStateException` is thrown.

## Example: Retrieving Input by Using Query Parameters

In this example, the `HelloWorld2.java` servlet example is modified to accept a username as a query parameter, in order to display a more personal greeting. The `service()` method is shown here.

Listing 7-1 Retrieving Input with the service() Method

>     public void service(HttpServletRequest req,
>              HttpServletResponse res)
>          throws IOException
>     {
>       String name, paramName[];
>       if ((paramName = req.getParameterValues("name"))
>           != null) {
>         name = paramName[0];
>       }
>       else {
>         name = defaultName;
>       }

>       // Set the content type first
>       res.setContentType("text/html");
>       // Obtain a PrintWriter as an output stream
>       PrintWriter out = res.getWriter();

>       out.print("<html><head><title>" +
>                   "Hello World!" + </title></head>");
>       out.print("<body><h1>");
>       out.print(defaultGreeting + " " + name + "!");
>       out.print("</h1></body></html>");
>     }

The `getParameterValues()` method retrieves the value of the `name` parameter from the HTTP query parameters. You retrieve these values in an array of type `String`. A single value for this parameter is returned and is assigned to the first element in the `name` array. If the parameter is not present in the query data, `null` is returned; in this case, `name` is assigned to the default name that was read from the `<init-param>` by the `init()` method.

Do not base your servlet code on the assumption that parameters are included in an HTTP request. The `getParameter()` method has been deprecated; as a result, you might be tempted to shorthand the `getParameterValues()` method by tagging an array subscript to the end. However, this method can return `null` if the specified parameter is not available, resulting in a `NullPointerException`.

For example, the following code triggers a `NullPointerException`:

>     String myStr = req.getParameterValues("paramName")[0];

Instead, use the following code:

>     if ((String myStr[] =
>               req.getParameterValues("paramName"))!=null) {
>       // Now you can use the myStr[0];
>     }
>     else {
>       // paramName was not in the query parameters!
>     }

## Securing Client Input in Servlets

The ability to retrieve and return user-supplied data can present a security vulnerability called cross-site scripting, which can be exploited to steal a user's security authorization. For a detailed description of cross-site scripting, refer to "Understanding Malicious Content Mitigation for Web Developers" (a CERT security advisory) at http://www.cert.org/tech_tips/malicious_code_mitigation.html.

To remove the security vulnerability, before you return data that a user has supplied, scan the data for any of the HTML special characters in Table 7-1. If you find any special characters, replace them with their HTML entity or character reference. Replacing the characters prevents the browser from executing the user-supplied data as HTML.

Table 7-1 HTML Special Characters that Must Be Replaced

Replace this special character: | With this entity/character reference:
--- | ---
`<` | `&lt;`
`>` | `&gt;`
`(``` | `&40;`
`)` | `&41;`
`#` | `&35;`
`&` | `&38;`

### Using a WebLogic Server Utility Method

WebLogic Server provides the `weblogic.servlet.security.Utils.encodeXSS()` method to replace the special characters in user-supplied data. To use this method, provide the user-supplied data as input. For example, to secure the user-supplied data in Listing 7-1, replace the following line:
`out.print(defaultGreeting + " " + name + "!");`

with the following:
`out.print(defaultGreeting + " " +
weblogic.security.servlet.encodeXSS(name) + "!");`

To secure an entire application, you must use the `encodeXSS()` method each time you return user-supplied data. While the previous example in Listing 7-1 is an obvious location in which to use the `encodeXSS()` method, Table 7-2 describes other locations to consider.

Table 7-2 Code that Returns User-Supplied Data

Page Type | User-Supplied Data | Example
--- | --- | ---
Error page | Erroneous input string, invalid URL, username | An error page that says "username is not permitted access."
Status page | Username, summary of input from previous pages | A summary page that asks a user to confirm input from previous pages.
Database display | Data presented from a database | A page that displays a list of database entries that have been previously entered by a user.

# Using Cookies in a Servlet

A cookie is a piece of information that the server asks the client browser to save locally on the user's disk. Each time the browser visits the same server, it sends all cookies relevant to that server with the HTTP request. Cookies are useful for identifying clients as they return to the server.

Each cookie has a name and a value. A browser that supports cookies generally allows each server domain to store up to 20 cookies of up to 4k per cookie.

## Setting Cookies in an HTTP Servlet

To set a cookie on a browser, create the cookie, give it a value, and add it to the `HttpServletResponse` object that is the second parameter in your servlet's service method. For example:

>     Cookie myCookie = new Cookie("ChocolateChip", "100");
>     myCookie.setMaxAge(Integer.MAX_VALUE);
>     response.addCookie(myCookie);

This examples shows how to add a cookie called `ChocolateChip` with a value of `100` to the browser client when the response is sent. The expiration of the cookie is set to the largest possible value, which effectively makes the cookie last forever. Because cookies accept only string-type values, you should cast to and from the desired type that you want to store in the cookie. When using EJBs, a common practice is to use the home handle of an EJB instance for the cookie value and to store the user's details in the EJB for later reference.

## Retrieving Cookies in an HTTP Servlet

You can retrieve a cookie object from the `HttpServletRequest` that is passed to your servlet as an argument to the `service()` method. The cookie itself is presented as a `javax.servlet.http.Cookie` object.

In your servlet code, you can retrieve all the cookies sent from the browser by calling the `getCookies()` method. For example:

>     Cookie[] cookies = request.getCookies();

This method returns an array of all cookies sent from the browser, or `null` if no cookies were sent by the browser. Your servlet must process the array in order to find the correct named cookie. You can get the name of a cookie using the `Cookie.getName()` method. It is possible to have more that one cookie with the same name, but different path attributes. If your servlets set multiple cookies with the same names, but different path attributes, you also need to compare the cookies by using the `Cookie.getPath()` method. The following code illustrates how to access the details of a cookie sent from the browser. It assumes that all cookies sent to this server have unique names, and that you are looking for a cookie called `ChocolateChip` that may have been set previously in a browser client.

>     Cookie[] cookies = request.getCookies();
>     boolean cookieFound = false;

>     for(int i=0; i < cookies.length; i++) {
>       thisCookie = cookies[i];
>       if (thisCookie.getName().equals("ChocolateChip")) {
>         cookieFound = true;
>         break;
>       }
>     }

>     if (cookieFound) {
>       // We found the cookie! Now get its value
>       int cookieOrder = String.parseInt(thisCookie.getValue());
>     }

## Using Cookies That Are Transmitted by Both HTTP and HTTPS

Because HTTP and HTTPS requests are sent to different ports, some browsers may not include the cookie sent in an HTTP request with a subsequent HTTPS request (or vice-versa). This may cause new sessions to be created when servlet requests alternate between HTTP and HTTPS. To ensure that all cookies set by a specific domain are sent to the server every time a request in a session is made, set the `cookie-domain` element to the name of the domain. The `cookie-domain` element is a subelement of the `session-descriptor` element in the WebLogic-specific deployment descriptor `weblogic.xml`. For example:

>     <session-descriptor>
>       <cookie-domain>mydomain.com</cookie-domain>
>     </session-descriptor>

The `cookie-domain` element instructs the browser to include the proper cookie(s) for all requests to hosts in the domain specified by `mydomain.com`. For more information about this property or configuring session cookies, see Setting Up Session Management.

## Application Security and Cookies

Using cookies that enable automatic account access on a machine is convenient, but can be undesirable from a security perspective. When designing an application that uses cookies, follow these guidelines:

- Do not assume that a cookie is always correct for a user. Sometimes machines are shared or the same user may want to access a different account.
- Allow your users to make a choice about leaving cookies on the server. On shared machines, users may not want to leave automatic logins for their account. Do not assume that users know what a cookie is; instead, ask a question like:

`Automatically login from this computer?`

- Always ask for passwords from users logging on to obtain sensitive data. Unless a user requests otherwise, you can store this preference and the password in the user's session data. Configure the session cookie to expire when the user quits the browser.

# Response Caching

The cache filter works similarly to the cache tag with the following exceptions:

- It caches on a page level (or included page) instead of a JSP fragment level.
- Instead of declaring the caching parameters inside the document you can declare the parameters in the configuration of the Web application.

The cache filter has some default behavior that the cache tag does not for pages that were not included from another page. The cache filter automatically caches the response headers Content-Type and Last-Modified. When it receives a request that results in a cached page it compares the If-Modified-Since request header to the Last-Modified response header to determine whether it needs to actually serve the content or if it can send an 302 SC_NOT_MODIFED status with an empty content instead.

The following example shows how to register a cache filter to cache all the HTML pages in a Web application using the filter element of the J2EE standard deployment descriptor, web.xml.

<filter>

<filter-name>HTML</filter-name>

<filter-class>weblogic.cache.filter.CacheFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>HTML</filter-name>

<url-pattern>*.html</url-pattern>

</filter-mapping>

The cache system uses soft references for storing the cache. So the garbage collector might or might not reclaim the cache depending on how recently the cache was created or accessed. It will clear the soft references in order to avoid throwing an OutOfMemoryError.

### Initialization Parameters

To make sure that if the web pages were updated at some point you got the new copies into the cache, you could add a timeout to the filter. Using the init-params you can set many of the same parameters that you can set for the cache tag:

The initialization parameters are

- `Name` This is the name of the cache. It defaults to the request URI for compatibility with *.extension URL patterns.
- `Timeout` This is the amount of time since the last cache update that the filter waits until trying to update the content in the cache again. The default unit is seconds but you can also specify it in units of ms (milliseconds), s (seconds), m (minutes), h (hours), or d (days).
- `Scope` The scope of the cache can be any one of request, session, application, or cluster. Request scope is sometimes useful for looping constructs in the page and not much else. The scope defaults to application. To use cluster scope you must set up the ClusterListener.
- `Key` This specifies that the cache is further specified not only by the name but also by values of various entries in scopes. These are specified just like the keys in the CacheTag although you do not have page scope available.
- `Vars` These are the variables calculated by the page that you want to cache. Typically this is used with servlets that pull information out of the database based on input parameters.
- `Size` This limits the number of different unique key values cached. It defaults to infinity.

The following example shows where the init-parameter is located in the filter code.

<filter>

<filter-name>HTML</filter-name>

<filter-class>weblogic.cache.filter.CacheFilter</filter-class>

<init-param>

- `Max-cache-size` This limits the`size of an element added to the cache. It defaults to 64k.`

# Using WebLogic Services from an HTTP Servlet

When you write an HTTP servlet, you have access to many rich features of WebLogic Server, such as JNDI, EJB, JDBC, and JMS.

The following documents provide additional information about these features:

- Programming WebLogic EJB
- Programming WebLogic JDBC
- Programming WebLogic JNDI
- Programming WebLogic JMS

# Accessing Databases

WebLogic Server supports the use of Java Database Connectivity (JDBC) from server-side Java classes, including servlets. JDBC allows you to execute SQL queries from a Java class and to process the results of those queries. For more information on JDBC and WebLogic Server, see Using WebLogic JDBC.

You can use JDBC in servlets as described in the following sections:

- Connecting to a Database Using a DataSource Object.
- Connecting Directly to a Database Using a JDBC Driver.

## Connecting to a Database Using a DataSource Object

A `DataSource` is a server-side object that references a connection pool. The connection pool registration defines the JDBC driver, database, login, and other parameters associated with a database connection. You create DataSource objects and connection pools through the Administration Console. Using a `DataSource` object is recommended when creating J2EE-compliant applications.

### Using a DataSource in a Servlet

1. Register a connection pool using the Administration Console. For more information, see JDBC Data Source: Configuration: Connection Pool
2. Register a `DataSource` object that points to the connection pool.
3. Look up the `DataSource` object in the JNDI tree. For example:

>     Context ctx = null;

>     // Get a context for the JNDI look up
>     ctx = new InitialContext(ht);

>     // Look up the DataSource object
>     javax.sql.DataSource ds
>             = (javax.sql.DataSource) ctx.lookup ("myDataSource");

4. Use the `DataSource` to create a JDBC connection. For example:

>     java.sql.Connection conn = ds.getConnection();

5. Use the connection to execute SQL statements. For example:

>     Statement stmt = conn.createStatement();
>     stmt.execute("select * from emp");

>     . . .

## Connecting Directly to a Database Using a JDBC Driver

Connecting directly to a database is the least efficient way of making a database connection because a new database connection must be established for each request. You can use any JDBC driver to connect to your database. BEA provides JDBC drivers for Oracle and Microsoft SQL Server. For more information, see Programming WebLogic JDBC.

# Threading Issues in HTTP Servlets

When you design a servlet, you should consider how the servlet is invoked by WebLogic Server under high load. It is inevitable that more than one client will hit your servlet simultaneously. Therefore, write your servlet code to guard against sharing violations on shared resources or instance variables.

It is recommended that shared-resource issues be handled on an individual servlet basis. Consider the following guidelines:

- Wherever possible, avoid synchronization, because it causes subsequent servlet requests to bottleneck until the current thread completes.
- Define variables that are specific to each servlet request within the scope of the service methods. Local scope variables are stored on the stack and, therefore, are not shared by multiple threads running within the same method, which avoids the need to be synchronized.
- Access to external resources should be synchronized on a Class level, or encapsulated in a transaction.

# Dispatching Requests to Another Resource

This section provides an overview of commonly used methods for dispatching requests from a servlet to another resource.

A servlet can pass on a request to another resource, such as a servlet, JSP, or HTML page. This process is referred to as request dispatching. When you dispatch requests, you use either the `include()` or `forward()` method of the `RequestDispatcher` interface.

For a complete discussion of request dispatching, see section 8.2 of the Servlet 2.4 specification (see ) from Sun Microsystems.

By using the `RequestDispatcher`, you can avoid sending an HTTP-redirect response back to the client. The `RequestDispatcher` passes the HTTP request to the requested resource.

To dispatch a request to a particular resource:

1. Get a reference to a `ServletContext`:

>     ServletContext sc = getServletConfig().getServletContext();

2. Look up the `RequestDispatcher` object using one of the following methods:

- `RequestDispatcher rd = sc.getRequestDispatcher(String` path);

path should be relative to the root of the Web Application.

- `RequestDispatcher rd = sc.getNamedDispatcher(String` name);

Replace name with the name assigned to the servlet in the J2EE standard Web Application deployment descriptor, web.xml, with the `<servlet-name>` element.

- `RequestDispatcher rd = ServletRequest.getRequestDispatcher(String path);`

This method returns a `RequestDispatcher` object and is similar to the `ServletContext.getRequestDispatcher(String` path) method except that it allows the path specified to be relative to the current servlet. If the path begins with a / character it is interpreted to be relative to the Web Application.

You can obtain a `RequestDispatcher` for any HTTP resource within a Web Application, including HTTP Servlets, JSP pages, or plain HTML pages by requesting the appropriate URL for the resource in the `getRequestDispatcher()` method. Use the returned `RequestDispatcher` object to forward the request to another servlet.

3. Forward or include the request using the appropriate method:

- `rd.forward(request,response);`
- `rd.include(request,response);`

These methods are discussed in the next two sections.

## Forwarding a Request

Once you have the correct `RequestDispatcher`, your servlet forwards a request using the `RequestDispatcher.forward()` method, passing `HTTPServletRequest` and `HTTPServletResponse` as arguments. If you call this method when output has already been sent to the client an `IllegalStateException` is thrown. If the response buffer contains pending output that has not been committed, the buffer is reset.

The servlet must not attempt to write any previous output to the response. If the servlet retrieves the `ServletOutputStream` or the `PrintWriter` for the response before forwarding the request, an `IllegalStateException` is thrown.

All other output from the original servlet is ignored after the request has been forwarded.

If you are using any type of authentication, a forwarded request, by default, does not require the user to be re-authenticated. You can change this behavior to require authentication of a forwarded request by adding the `check-auth-on-forward/` element to the `container-descriptor` element of the WebLogic-specific deployment descriptor, `weblogic.xml`. For example:

>     <container-descriptor>
>         <check-auth-on-forward/>
>     </container-descriptor>

## Including a Request

Your servlet can include the output from another resource by using the `RequestDispatcher.include()` method, and passing `HTTPServletRequest` and `HTTPServletResponse` as arguments. When you include output from another resource, the included resource has access to the request object.

The included resource can write data back to the `ServletOutputStream` or `Writer` objects of the response object and then can either add data to the response buffer or call the `flush()` method on the response object. Any attempt to set the response status code or to set any HTTP header information from the included servlet response is ignored.

In effect, you can use the `include()` method to mimic a "server-side-include" of another HTTP resource from your servlet code.

## RequestDispatcher and Filters

The Servlet 2.3 Specification from Sun Microsystems did not specify whether filters should be applied on forwards and includes. The Servlet 2.4 specification clarifies this by introducing a new dispatcher element in the web.xml deployment descriptor. Using this dispatcher element, you can configure a filter-mapping to be applied on REQUEST/FORWARD/INCLUDE/ERROR. In WebLogic Server 8.1, the default was REQUEST+FORWARD+INCLUDE. For the old DTD-based deployment descriptors, the default value has not been changed in order to preserve backward compatibility. For the new descriptors (schema based) the default is REQUEST.

You can change the default behavior of dispatched requests by setting the filter-dispatched-requests-enabled element in weblogic.xml. This element controls whether or not filters are applied to dispatched (include/forward) requests. The default value for old DTD-based deployment descriptors is true. The default for the new schema-based descriptors is false

For more information about RequestDispatcher and filters, see section 6.2.5 of the Servlet 2.4 specification. For more information about writing and configuring filters for WebLogic Server, see Filters.

# Proxying Requests to Another Web Server

The following sections discuss how to proxy HTTP requests to another Web server:

- Overview of Proxying Requests to Another Web Server
- Setting Up a Proxy to a Secondary Web Server
- Sample Deployment Descriptor for the Proxy Servlet

## Overview of Proxying Requests to Another Web Server

When you use WebLogic Server as your primary Web server, you may also want to configure WebLogic Server to pass on, or proxy, certain requests to a secondary Web server, such as Netscape Enterprise Server, Apache, or Microsoft Internet Information Server. Any request that gets proxied is redirected to a specific URL.You can even proxy to another Web server on a different machine.You proxy requests based on the URL of the incoming request.

The `HttpProxyServlet` (provided as part of the distribution) takes an HTTP request, redirects it to the proxy URL, and sends the response to the client's browser back through WebLogic Server. To use the `HttpProxyServlet`, you must configure it in a Web Application and deploy that Web Application on the WebLogic Server that is redirecting requests.

## Setting Up a Proxy to a Secondary Web Server

To set up a proxy to a secondary HTTP server:

1. Register the `proxy` servlet in your Web Application deployment descriptor (see Sample web.xml for Use with ProxyServlet)`.` The Web Application must be the default Web Application of the server instance that is responding to requests. The class name for the proxy servlet is `weblogic.servlet.proxy.HttpProxyServlet.`
2. Define an initialization parameter for the `ProxyServlet` with a `<param-name>` of `redirectURL` and a `<param-value>` containing the URL of the server to which proxied requests should be directed.
3. Map the `ProxyServlet` to a `<url-pattern>`. Specifically, map the file extensions you wish to proxy, for example `*.jsp`, or *`.html`. Use the `<servlet-mapping>` element in the `web.xml` Web Application deployment descriptor.

If you set the `<url-pattern>` to "`/`", then any request that cannot be resolved by WebLogic Server is proxied to the remote server. However, you must also specifically map the following extensions: `*.jsp`, `*.html`, and `*.html` if you want to proxy files ending with those extensions.

4. Deploy the Web Application on the WebLogic Server instance that redirects incoming requests.

## Sample Deployment Descriptor for the Proxy Servlet

The following is an sample of a Web applications deployment descriptor for using the `ProxyServlet`.

Listing 7-2 Sample web.xml for Use with ProxyServlet

>     <?xml version="1.0" encoding="UTF-8"?>

>     <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"

>     	    targetNamespace="http://java.sun.com/xml/ns/j2ee"

>     	    xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"

>     	    xmlns:xsd="http://www.w3.org/2001/XMLSchema"

>     	    elementFormDefault="qualified"

>     	    attributeFormDefault="unqualified"

>     	    version="2.4">
>     <web-app>

>     <servlet>
>       <servlet-name>ProxyServlet</servlet-name>
>       <servlet-class>weblogic.servlet.proxy.HttpProxyServlet</servlet-class>

>       <init-param>
>         <param-name>redirectURL</param-name>
>         <param-value>
>            http://server:port
>         </param-value>
>       </init-param>

>     </servlet>

>     <servlet-mapping>
>       <servlet-name>ProxyServlet</servlet-name>
>       <url-pattern>/</url-pattern>
>     </servlet-mapping>

>     <servlet-mapping>
>       <servlet-name>ProxyServlet</servlet-name>
>       <url-pattern>*.jsp</url-pattern>
>     </servlet-mapping>

>     <servlet-mapping>
>       <servlet-name>ProxyServlet</servlet-name>
>       <url-pattern>*.htm</url-pattern>
>     </servlet-mapping>

>     <servlet-mapping>
>       <servlet-name>ProxyServlet</servlet-name>
>       <url-pattern>*.html</url-pattern>
>     </servlet-mapping>

>     </web-app>

# Clustering Servlets

Clustering servlets provides failover and load balancing benefits. To deploy a servlet in a WebLogic Server cluster, deploy the Web Application containing the servlet on all servers in the cluster.

For information on requirements for clustering servlets, and to understand the connection and failover processes for requests that are routed to clustered servlets, see Replication and Failover for Servlets and JSPs in Using WebLogic Server Clusters.

Note: Automatic failover for servlets requires that the servlet session state be replicated in memory. For instructions, see Configure In-Memory HTTP Replication in Using WebLogic Server Clusters.

For information on the load balancing support that a WebLogic Server cluster provides for servlets, and for related planning and configuration considerations for architects and administrators, see Load Balancing for Servlets and JSPs in Using WebLogic Server Clusters.

# Referencing a Servlet in a Web Application

The URL used to reference a servlet in a Web Application is constructed as follows:

>     	http://myHostName:port/myContextPath/myRequest/?myRequestParameters

The components of this URL are defined as follows:

  `myHostName`

  The DNS name mapped to the Web Server defined in the WebLogic Server Administration Console.

  This portion of the URL can be replaced with `host:port`, where `host` is the name of the machine running WebLogic Server and `port` is the port at which WebLogic Server is listening for requests.

  `port`

  The port at which WebLogic Server is listening for requests. The Servlet can communicate with the proxy only through the listenPort on the Server mBean and the SSL mBean.

  `myContextPath`

  The name of the context root which is specified in the weblogic.xml file, or the uri of the web module which is specified in the config.xml file.

  `myRequest`

  The name of the servlet as defined in the `web.xml` file.

  `myRequestParameters`

  Optional HTTP request parameters encoded in the URL, which can be read by an HTTP servlet.

# URL Pattern Matching

WebLogic Server provides the user with the ability to implement a URL matching utility which does not conform to the J2EE rules for matching. The utility must be configured in the weblogic.xml deployment descriptor rather than the web.xml deployment descriptor used for the configuration of the default implementation of URLMatchMap.

To be used with WebLogic Server, the URL matching utility must implement the following interface:

`Package weblogic.servlet.utils;`

`public interface URLMapping {`

`public void put(String pattern, Object value);`

`public Object get(String uri);`

`public void remove(String pattern)`

`public void setDefault(Object defaultObject);`

`public Object getDefault();`

`public void setCaseInsensitive(boolean ci);`

`public boolean isCaseInsensitive();`

public int size();

public Object[] values();

public String[] keys();

}

# The SimpleApacheURLMatchMap Utility

The included SimpleApacheURLMatchMap utility is not J2EE specific. It can be configured in the weblogic.xml deployment descriptor file and allows the user to specify Apache style pattern matching rather than the default URL pattern matching provided in the web.xml deployment descriptor. For more information, see url-match-map.

# Avoiding Hung Threads

In general, WebLogic Server processes incoming HTTP requests and the response is returned immediately to the client. Such connections are handled synchronously by the same thread.

However, some HTTP requests may require longer processing time. Database connection, for example, may create longer response times. Handling these requests synchronously causes the thread to be held, waiting until the request is processed and the response sent.

To avoid this hung-thread scenario, WebLogic Server provides two classes that handle HTTP requests asynchronously by de-coupling the response from the thread that handles the incoming request.

The following sections describe these classes.

## Future Response Servlet

Use the Future Response Servlet to handle servlet responses with a different thread than the one that handles the incoming request. You enable this servlet by extending weblogic.servlet.FutureResponseServlet.java, which gives you full control over how the response is handled and allows more control over thread handling. However, using this class to avoid hung threads requires you to provide most of the code.

The exact implementation depends on your needs, but you must override the service() method of this class at a minimum. The following example shows how you can override the service method.

Listing 7-3 Overriding the service() method of FutureResponseServlet.java

>     public void service(HttpServletRequest request, FutureServletResponse response)

>                 throws IOException, ServletException

>         {

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

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

>     		String method   =request.getMethod();

>     		try

>     		{

>     			HttpURLConnection urlConn = (HttpURLConnection) new URL("http://"+host+":"+port+"/nonblockingbackend/echo").openConnection();

>     			urlConn.setRequestMethod(method);

>     			urlConn.setDoInput(true);

>     			urlConn.setDoOutput(true);

>     	    	urlConn.setUseCaches (false);

>     		    urlConn.setAllowUserInteraction(true);

>     		    urlConn.setFollowRedirects(true);

>     		    urlConn.setInstanceFollowRedirects(true);

>     		    urlConn.setRequestProperty ("Content-Type","application/x-www-form-urlencoded");

>     //			String content = "wait=" + URLEncoder.encode(waitTime);

>     			DataOutputStream os = new DataOutputStream(urlConn.getOutputStream());

>     //	        os.writeBytes (content);

>     			copyCompletely(request.getInputStream(), os);

>     			os.flush();

>     			urlConn.connect();

>     			AsyncResponseHandler.getInstance().writeRequestAndRegister(

>     					urlConn,

>     					new RetrieveHttpResponseWork(response));

>         		}

>     		catch (Exception e)

>     		{

>     			e.printStackTrace();

>     			response.setStatus(FutureServletResponse.SC_INTERNAL_SERVER_ERROR);

>     			response.flushBuffer();

>     			response.send();

>     		}

## Abstract Asynchronous Servlet

Like the Future Response Servlet, the Abstract Asynchronous Servlet enables you to handle incoming requests and servlet responses with different threads. Unlike the Future Response Servlet, this class explicitly provides more of the general framework for handling the response, including thread handling.

You implement the Abstract Asynchronous Servlet by extending weblogic.servlet.http.AbstractAsyncServlet.java. This class provides the following abstract methods which you must override in your extended class.

### doRequest

This method processes the servlet request. The following code example demonstrates how to override this method.

Listing 7-4 Overriding doRequest in AbstractAsynchServlet.java

>     public boolean doRequest(RequestResponseKey rrk)
>           throws ServletException, IOException {
>           HttpServletRequest req = rrk.getRequest();
>           HttpServletResponse res = rrk.getResponse();

>           if (req.getParameter("immediate") != null) {
>                 res.setContentType("text/html");
>                 PrintWriter out = res.getWriter();
>                 out.println("Hello World Immediately!");
>                 return false ;
>           }
>           else {
>                 TimerManagerFactory.getTimerManagerFactory()
>                 .getDefaultTimerManager().schedule
>                 (new TimerListener() {
>                       public void timerExpired(Timer timer)
>                             {try {
>                                   AbstractAsyncServlet.notify(rrk, null);
>                             }
>                             catch (Exception e) {
>                                   e.printStackTrace();
>                             }
>                       }
>                 }, 2000);
>           return true;
>           }
>     }

### doResponse

This method processes the servlet response.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doResponse() method.

If an exception occurs during processing, the container returns an error to the client. The following code example demonstrates how to override this method.

Listing 7-5 Overriding doResponse() in AbstractAsyncServlet.java

>     public void doResponse (RequestResponseKey rrk, Object context)
>        throws ServletException, IOException
>           {
>           HttpServletRequest req = rrk.getRequest();
>           HttpServletResponse res = rrk.getResponse();

>           res.setContentType("text/html");
>           PrintWriter out = res.getWriter();
>           out.println("Hello World!");
>     }

### doTimeOut

This method sends a servlet response error when the notify() method is not called within the timeout period.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doTimeOut() method.

Listing 7-6 Overriding doTimeOut() in AbstractAsyncServlet.java

>     public void doTimeout (RequestResponseKey rrk)
>           throws ServletException, IOException
>     {
>           HttpServletRequest req = rrk.getRequest();
>           HttpServletResponse res = rrk.getResponse();

>           res.setContentType("text/html");
>           PrintWriter out = res.getWriter();
>           out.println("Timeout!");
>     }