Corporate Info | News | Solutions | Products | Partners | Services | Events | Download | How To Buy

Using WebLogic HTTP Servlets

What Is a Servlet?

Servlets and JSP

Servlets and Web Applications

Overview of HTTP Servlet Support in Weblogic Server

How WebLogic Server Implements Servlets

WebLogic HTTP Servlet API Reference

Steps to Write a Basic HTTP servlet

Advanced Features

The Complete HelloWorldServlet Example

Initializing a Servlet

Initializing a Servlet at Server Startup

Using Initialization Parameters

Overriding the init() Method

Providing an HTTP Response

Retrieving Client Input

Other Methods of HttpServletRequest

Example: Retrieving Input by Using Query Parameters

Using Session Tracking From a Servlet

A History of Session Tracking

Tracking a Session with the HttpSession Object

The Lifetime of a Session

How Session Tracking Works

Detecting the Start of a Session

Setting and Getting Session Name/Value Attributes

ClassCastException and HTTP Sessions

Logging Out and Ending a Session

Configuring Session Tracking

Using URL Rewriting

URL rewriting and Wireless Access Protocol (WAP)

Making Sessions Persistent

Scenarios To Avoid When Using Sessions

Use Serializable Attribute Values

Configuring Session Persistence

Using Cookies in a Servlet

Setting Cookies in an HTTP servlet

Retrieving Cookies in an HTTP Servlet

Using Cookies that Will Be Transmitted by Both HTTP and HTTPS

Your Application Security and Cookies

Using WebLogic Services from an HTTP Servlet

Accessing Databases-Using Connection Pools in a Servlet

Setting up the Registration for a Connection Pool

Using a Connection Pool in a Servlet

Threading Issues in HTTP Servlets

Passing the Request to Another HTTP Servlet

Forwarding a Request

Including a Request

Using Server-Side Includes

Setting up ACLs for Servlets in the WebLogic Realm

Setting ACLs for Groups of Servlets

Using the ServletServlet -- a Developer's Shortcut

Disadvantages of Using the ServletServlet

Using the Servlet Classpath

Tips for Using the Servlet Classpath

Clustering Servlets

Overview

What Is a Servlet?

In generic terms, a servlet is any class that can be invoked and executed on a server, most likely on behalf of a client. Unlike applets, which do their work on the client, servlets do their work on the server and are often used to replace Common Gateway Interface (CGI) or other server-side programming models. Another way of phrasing what servlets do is "server-side Java." Since servlets are written in Java and are part of the J2EE specification, they have access to all the functionality and cross-platform portability of the Java programming language.

So, what is an HTTP servlet? An HTTP servlet is a Java class that handles an HTTP request and delivers an HTTP response. HTTP servlets live in an HTTP server and must extend the javax.servlet.http.HttpServlet class, so that they can run in a generic servlet engine framework.

WebLogic Server can be configured as a fully functional HTTP Server that delivers any arbitrary MIME type to HTTP clients. For more information on setting this up, see the Administrators Guide, Setting up WebLogic as an HTTP Server. To provide more complex Web pages that accept input from the client and provide dynamic responses, you must write your own custom HTTP servlets. You can develop sophisticated Web sites, such as shopping-carts or online booking forms by combining WebLogic Server's built-in services such as EJB, JDBC, and JSP with HTTP servlets.

When you write HTTP servlets and register them with WebLogic Server, the servlets operate within the security framework of WebLogic Server, and are used to service HTTP requests from clients. The work performed by HTTP servlets can be compared to that of CGI scripts, but HTTP servlets are more effective for the following reasons:

- HTTP servlets are written in a well-formed, and compiled language-Java, so they are more robust than "interpreted" scripts.

- Servlets can access any of the Java language APIs.

- CGI scripts fork a new process to handle each request. If the process requires accessing resources such as databases, the CGI script must open (and subsequently close) a new database connection to handle each request, which is needlessly time consuming. Servlets, on the other hand, run in an existing process that is already running in WebLogic Server. The resources (such as database connections) required to handle the request are already available to quickly process the request.

- Servlets can be protected by the robust security of the server-unlike some CGI scripts that are hazardous.

- Servlets interact with the HTTP request by way of a a well-developed programmatic interface and are easier to write and less prone to errors.

WebLogic Server implements the Java HTTP servlet 2.2 API, available at: http://java.sun.com/products/servlet/2.2/index.html. message URL

Servlets and JSP

This document details how to use HTTP servlets to perform server-side Java tasks in response to HTTP requests. For Web services that require more sophisticated presentation, you should use Java Server Pages. With JSP you write the static HTML content directly, and embed Java code into the HTML page, as opposed to servlets which can embed HTML code inside of Java code to produce an HTML page. These two technologies are often used together as integral parts of a Web application.

Servlets and Web Applications

The HTTP servlet 2.2 specification introduces the new concept of a Web Application, which allows resources for a server-side application to be bundled together and deployed as a unit. For details on developing and deploying Web Applications on WebLogic Server, see the developers guide Writing a Web Application.

Overview of HTTP Servlet Support in Weblogic Server

The code in your HTTP servlets can use all of WebLogic Server's server-side services, including EJB, RMI, and JDBC. Below is an overview of the support services available to HTTP servlets:

Session tracking
  Session tracking allows a Web site to track a user's progress across multiple Web pages. This functionality supports Web sites such as e-commerce sites that use shopping carts. WebLogic supports session persistence to a database, providing fail-over between server down time and session sharing between clustered servers.

Database access
  Your servlets can use JDBC drivers (including BEA's) for basic database access. With Weblogic Server's multitier JDBC driver, you can take advantage of connection pools, server-side data caching, and other multitier features.

Configuration and management
  The WebLogic Console (see http://www.weblogic.com/docs51/admindocs/console.html) provides an integrated GUI tool for administration of servlets.

Security
  WebLogic Server has built-in security, using the secure sockets layer (SSL) for authentication and encryption of client-to-server communications, and access control lists (ACLs) for configurable allocation of server resources.

Logging and report generation
  HTTP requests are logged in the access.log file in common or extended log format that you can configure (see the Administrators Guide document, Setting Up WebLogic as an HTTP server.) WebLogic Server can be configured to submit events to WebLogic's Event Topic Tree for each HTTP request, providing detailed common-log fields. You can write report-generating applications that register interest in these HTTP events.

Integrated services
  WebLogic HTTP servlets is one of the many services available to WebLogic applications, including JDBC, RMI, EJB, Events, and JavaBeans. The APIs for all of WebLogic's services and facilities share many common aspects that make building a complex networked application easier; your application may use several services, all of which can share access to objects and client resources.

How WebLogic Server Implements Servlets

HTTP servlets are a major part of WebLogic Server's HTTP capabilities. In fact, WebLogic Server fulfills all its HTTP requirements using a set of pre-built HTTP servlets that are implemented and registered exactly as you would write and register your own custom servlets. For instance, in WebLogic Server:

- Requests for HTML pages and accompanying HTTP data are all handled by an internal servlet called the FileServlet.

- Server-side includes, or ".shtml" files, are handled by an internal servlet called the ServerSideIncludeServlet.

- JSP pages are handled by an internal servlet called the JSPServlet.

- Applets and other class files are served to Web-clients by an internal servlet called the ClasspathServlet.

These internal servlets are registered in the weblogic.properties file. You can call these servlets from an HTTP client and integrate their features in to your Web application. For a more detailed description of these servlets, see Registering the WebLogic Servlets.

After you write your own HTTP servlets, you register them in the weblogic.properties file in exactly the same way as the standard internal servlets that are shipped with WebLogic Server. Your custom servlets are treated exactly like the standard HTTP servlets that provide the HTTP capabilities.

Each HTTP servlet is registered against a specific URL pattern, so that when a matching URL is requested, the corresponding servlet is called upon to handle the request. For details on registering HTTP servlets with WebLogic Server, see the WebLogic Administrators Guide, Registering user-written servlets.

WebLogic HTTP Servlet API Reference

WebLogic supports the javax.servlet.http package in the Java Servlet 2.2 API. You can find documentation for the package at Sun.

Package javax.servlet

Package javax.servlet.http

Introduction to Programming

Steps to Write a Basic HTTP servlet

The section contains a description of the basic steps for writing an HTTP servlet. A complete code example (the HelloWorldServlet) illustrating these steps is included at the end of this chapter. Additional information on using various J2EE and Weblogic Server services such as JDBC, RMI, and JMS in your servlet are discussed later in this document.

1. Import the appropriate packages and classes, including:

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

2. Extend javax.servlet.http.HttpServlet.

       public class HelloWorldServlet extends HttpServlet{

3. Implement a service() method. The main function of a servlet is to accept an HTTP request from a Web Browser, and return an HTTP response. This work is done by your servlet's service() method. The service methods include response objects that you use to create output and request objects used to receive data from the client.

   You may have seen other servlet examples implement the doPost() and/or doGet() methods. These reply only to POST or GET requests; If you want to handle all request types from a single method, your servlet can simply implement the service() method. (However, if you choose to implement the service() method, you will not be able to implement the doPost() or doGet() methods -- unless you call super.service() at the beginning of the service() method.) The HTTP servlet specification describes other methods used to handle other less-common request types, however all of these methods are collectively referred to as service methods.

   All of the service methods take the same parameter arguments; an HttpServletRequest provides information about the request, and an HttpServletResponse, is used by your servlet to reply to the HTTP client.

       public void service(HttpServlet Request req,
              HttpServletResponse res) throws IOException
       {

4. Set the content type.

       res.setContentType("text/html");

5. Obtain a PrintWriter object to use for output.

       PrintWriter out = res.getWriter();

6. Create some HTML using the PrintWriter object

       out.println("<html><head><title>Hello World!</title></head>");
       out.println("<body><h1>Hello World!</h1></body></html>");
         }
       }

7. Compile the servlet

   1. Open a new command shell, and run the setEnv script provided in the root directory of the WebLogic installation. If necessary, edit the script in a text editor to point to the correct JDK and WebLogic home directory.

   2. In the directory containing your servlet Java source code, compile and place your servlet class in the servlet classpath . The setEnv script sets the environment variable %SERVLET_CLASSES% to point to the default servlet classpath directory. You can now compile you servlet with:

          $  javac -d %SERVLET_CLASSES% myservlet.java

      The servlet classpath is set up to point to the %SERVLET_CLASSES% directory in the weblogic.properties file, with the property:

          weblogic.httpd.servlet.classpath=\
            c:/weblogic/myserver/servletclasses

      Search for the property in the weblogic.properties file and uncomment it if necessary.

8. Deploy the servlet on WebLogic Server so that it can be called from a Web browser client. There are many configuration options you can use when deploying your servlet. There are also some deployment options that are helpful in the development stage, such as options that allow you to deploy a servlet without re-starting WebLogic Server (These options are not recommended for a production environment).

   Here are a number of ways you can deploy servlets that will suit different situations:

   - Register the servlet in the weblogic.properties file. This will deploy the servlet whenever WebLogic Server is started (or restarted):

         weblogic.httpd.register.hello=\
             examples.servlets.HelloWorldServlet

     You may also set ACLs for servlets deployed via the weblogic.properties file. This is described in more detail in the Administrators Guide Setting WebLogic Properties.

   - Hot deploy the servlet from the WebLogic Console.

     You may temporarily deploy or un-deploy a servlet from the WebLogic Console without stopping WebLogic Server. See the Deployment Guide Using WebLogic Server hot deploy. To make this a permanent configuration, you must also register the servlet in the weblogic.properties file, as described above.

   - Call the servlet via the ServletServlet.

     The ServletServlet allows you to call any servlet class on the server, even if it is not registered or hot-deployed. This has security and performance disadvantages, but is useful while you are prototyping in the development phase. We recommend that you do not register the ServletServlet in a production system. For more information, see Using the ServletServlet -- a Developer's Shortcut.

9. Call the servlet from a browser

   To invoke a servlet from a browser you encode the servlet's URL into a page link, or an HTML form. However, you can test your HTTP servlet directly by typing the servlet URL into the URL location bar on a Web browser, after the pattern:

       http://host:port/virtualName?servletArgs

   For our example, running on a WebLogic Server at the default location, enter this URL:

         http://localhost:7001/Hello

Advanced Features

The above procedures create a basic servlet. You will probably want to use some of the more advanced features of servlets, which are described briefly below:

- Handling HTML form data received from the client. HTTP servlets can receive and process data received from a browser client in HTML forms.

  - Retrieving Client Input.

- HTTP servlets offer many ways to architect your application. These sections provide detailed information on writing servlets:

  - Providing an HTTP Response.

  - Threading Issues in HTTP Servlets.

  - Passing the Request to Another HTTP Servlet.

- Initializing a servlet. Overriding the init() method. If your servlet needs to initialize some data, accept initialization arguments, or perform other actions when the servlet is initialized, you can override the init() method.

  - Initializing a Servlet.

- Use sessions and persistence in your servlet. Sessions and persistence allow you to track your users within and between HTTP sessions. Session management includes the use of cookies.

  - Using Session Tracking From a Servlet.

  - Using Cookies in a Servlet.

- Using WebLogic services in your servlet. WebLogic Server provides a variety of services and APIs that you can use in your Web applications. These include Java Database Connectivity (JDBC) drivers, JDBC database connection pools, Java Messaging Service (JMS), Enterprise JavaBeans (EJB), and Remote Method Invocation (RMI).

  - Using WebLogic Services from an HTTP Servlet .

  - Setting up ACLs for Servlets in the WebLogic Realm

  - Accessing Databases-Using Connection Pools in a Servlet .

The Complete HelloWorldServlet Example

This is the complete Java source code for the example used in the above steps. The example is a simple servlet that provides a response to an HTTP request. Later, this example will be expanded to illustrate how to use HTTP parameters, cookies, and session tracking.

You can find the source and instructions on how to compile and run all the examples used in this document in the examples/servlets directory of your WebLogic Server distribution. The WebLogic Server examples are also available as a zip archive.

Listing 3-1 HelloWorldServlet.java

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

    public class HelloWorldServlet extends HttpServlet {
      public void service(HttpServletRequest req,
                          HttpServletResponse res)
           throws IOException
      {
        // Must set the content type first
        res.setContentType("text/html");
        // Now obtain a PrintWriter to insert HTML into
        PrintWriter out = res.getWriter();

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

Programming Tasks

Initializing a Servlet

When a servlet is initialized, WebLogic Server executes the servlet's init() method. Once the servlet has been initialized, it is not initialized again until you re-start WebLogic Server, unless the servlet is modified and reloaded. You can have your servlet perform certain tasks, such as establishing database connections, at initialization by overriding the init() method.

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 re4quest is made for the modified servlet, the modified servlet's init() method is executed.

Initializing a Servlet at Server Startup

You can also configure WebLogic Server to initialize a servlet immediately after the server is started by adding the following lines to the weblogic.properties file. Use this feature if your servlet initialization has a noticeable delay the first time it is called, or if your servlet needs to be active upon server startup.

    # Here we register the myservletclass servlet class
    weblogic.httpd.register.MyServlet=\
        examples.servlets.myservletclass
    # Configure the ServletStartup class to run MyServlet's init()
    # method at startup
    weblogic.system.startupClass.StartMyServlet=\
        weblogic.servlet.utils.ServletStartup
    weblogic.system.startupArgs.StartMyServlet=\
      servlet=MyServlet

where myservletclass is the servlet you want to initialize when you start WebLogic Server, associated here with the virtual name MyServlet.

At startup, the initialization process works as follows:

1. The ServletStartup class is registered as a system.startupClass and is invoked immediately after the server is started.

2. The ServletStartup class initializes the servlet with the virtual name specified as it is "server" parameter in its startupArgs.

To initialize more than one servlet at server startup time, you must register the ServletStartup class multiple times, using a different virtual name for each servlet. It is a good idea to follow a naming convention, such as that used above, so that you do not use conflicting virtual names and can keep track of registrations.

Using Initialization Parameters

You can use the weblogic.properties file to pass parameters to an HTTP servlet at its initialization. This allows you to customize the behavior of your servlet without having to recompile it. You associate the parameters with the servlet via its virtual name. For example, if the HelloWorldServlet is registered with the virtual name Hello, you can pass it initialization arguments using:

      weblogic.httpd.register.Hello=examples.servlets.HelloWorld
      weblogic.httpd.initArgs.Hello=greeting=howdy,person=stranger

For more information on registering servlets, read the Administrators Guide, Setting WebLogic Properties.

You retrieve initialization parameters by calling 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 perform actions at initialization time by overriding the init() method. It is important that you call the overridden init() method in the super class, so that it may parse the initialization arguments. It is generally a good idea to make this the first line in your implementation of the init() method.

The code fragment below reads initArgs that define a greeting, and a default name that can be customized from the weblogic.properties file.

     String defaultGreeting;
     String defaultName;

     public void init(ServletConfig config)
         throws ServletException {
       super.init(config);

       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. Note that the code provides default values for these variables if the initArgs property is missing from the weblogic.properties file by testing to see if the getInitParameter() method returns null.

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

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

The full source code and instructions for compiling, installing, and trying out an example called HelloWorld2, which illustrates the use of the init() method can be found in the WebLogic distribution examples/servlets directory. Do not forget to add the initArgs property to the servlet registration in the properties file:

    weblogic.httpd.register.Hello2=examples.servlets.HelloWorld2
    weblogic.httpd.initArgs.Hello2=\
        greeting=howdy,person=stranger

After you restart WebLogic Server, view the servlet in your browser with this URL:

      http://localhost:7001/Hello2

Providing an HTTP Response

This section describes how your HTTP servlet provides a response to the client. All responses should be delivered using the HttpServletResponse object that is passed as a parameter to the service() method of your servlet.

1. Configure the HttpServletResponse.

   You can set several servlet properties through the HttpServletResponse object that translate into HTTP header information. At a minimum, set the content type using the setContentType() method, even 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");

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

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

   You can 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.

        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. For the most part, this means you must send back the contents of an HTML page. Your servlet sends back an HTTP response via an output stream that you obtain using the response parameter of the service() method. To send an HTTP response:

   1. Obtain an output stream using the HttpServletResponse object. For example:

          PrintWriter out = res.getWriter();

          /or

          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.

   2. 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>");

      Do not close the output stream using the close() method and avoid flushing the stream's contents. Not closing or flushing the output stream, allows WebLogic Server to take advantage of persistent HTTP connections, as described in the next step.

3. Optimize the response

   WebLogic Server attempts to use HTTP persistent connections by default whenever possible. A persistent connection attempts to reuse the same HTTP TCP/IP connection for subsequent communications between client and server. Application performance improves because new connections need not be opened for immediate subsequent requests. This is a common requirement for HTML pages containing many in-line images, where each request image would otherwise require a TCP/IP connection.

   You can configure the amount of time that WebLogic Server keeps an HTTP connection open with the KeepAlive properties. For more information, see Configuring persistent HTTP connections.

   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 will be unable to 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 .

Retrieving Client Input

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

An HTTP request from a Web browser can be accompanied by other information besides the URL, such as information about the client, the browser, cookies, and user query parameters. Query parameters are used to carry user input from the browser, and are either appended to the URL address (the GET method) or included in the HTTP request body (the POST method).

HTTP servlets need not deal with these details; all of the information in the request is automatically available through the HttpServletRequest object and accessible by using the request.getParameters() method, regardless of the send method.

You can send query parameters from the client in a number of ways:

- 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 a name=value pair so ordering is not important. The following link might be placed in a Web page, sending the parameter "color" with value "purple" to an HTTP servlet called ColorServlet (to be entered on one line):

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

- Manually enter the URL with query parameters into the browser location. This is equivalent to clicking on the link shown in the above 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. You specify the method that the form uses 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 the query, and fetch each parameter value using its parameter name. A parameter usually has only one value, but can hold an array of values. Parameter values are always interpreted as Strings, so you may need to cast them to a more appropriate type.

This 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());
        }
      }

Other Methods of HttpServletRequest

HttpServletRequest.getMethod()
  Allows you to determine the request method, such as a GET or a POST.

HttpServletRequest.getQueryString()
  Allows you to access the query string-the remainder of the requested URL following the "?" character.

Example: Retrieving Input by Using Query Parameters

In this example, the HelloWorld2 servlet example is modified to accept a username as a query parameter, to build in a more personal greeting. The modified example is called HelloWorld3.java. The source code for the HelloWorld3.java example is included in the distribution in the examples\servlets directory. The service() method from the HellowWorld2 example is implemented as shown here:

      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, which 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 initArgs property by the init() method.

Compile and install the servlet example, then invoke it using the ServletServlet and the servlet classpath, using this URL in your browser (on one line):

    http://localhost:7001/servlets/examples/servlets/
      HelloWorld3?name=yourNameHere

Your code should never assume that parameters are included in an HTTP request. Since the deprecation of the getParameter() method, 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 parameter is not available, resulting in a NullPointerException. For example:

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

Instead, use:

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

Using Session Tracking From a Servlet

Session tracking enables you to track a user's progress over multiple servlets or HTML pages, which by nature are stateless. A "session" is defined as a series of browser requests that come from the same client, and are often related, during a certain time period. Session tracking ties together a series of browser requests-think of these as pages-that may have some meaning as a whole, such as a shopping cart application.

A History of Session Tracking

Before session tracking matured conceptually, developers tried to build state into their pages by stuffing information into hidden fields on a page or embedding user choices into URLs used in links with a long string of appended characters. You can see good examples of this at most search engine sites, many of which still depend on CGI. These sites track user choices with URL parameter name/value pairs that are appended to the URL, after the reserved HTTP character "?". This can result in a very long URL that the CGI script must carefully parse and manage. The problem with this approach is that you cannot pass this information from session to session. Once you lose control over the URL-that is, once the user leaves one of your pages-the user information is lost forever.

Later, Netscape introduced browser cookies, which you can use to store user-related information on the client for each server. However, some browsers still do not fully support cookies, and some users prefer to turn off the "cookie" option in their browsers. Another factor that should be considered is that most browsers limit the amount of data that can be stored with a cookie.

The HTTP servlet specification defines a solution that allows the server to store user details in a tangible place on the server, and protects your code from the complexities of tracking sessions. Your servlets can use an HttpSession object to track a user's input over the span of a single session and share session details between multiple servlets.

Tracking a Session with the HttpSession Object

Under the Java Servlet API, which WebLogic Server implements and supports, each servlet can access a server-side session by using its HttpSession object. An HttpSession object is your servlet's view of the session. You can access an HttpSession in the servlet's service() method using the HttpServletRequest object, depicted as the variable request here:

      HttpSession session = request.getSession(true);

An HttpSession object is created if one doesn't already exist for that client when the request.getSession(true) method is called with the argument true. The session object lives on WebLogic Server for the lifetime of the session, during which the session object accumulates information related to that client. Your servlet adds to or removes information from the session object as necessary. A session is associated with a particular client, although that user might not be identified as anything other than anonymous. Each time the client visits your servlet, the same associated HttpSession object is retrieved when the getSession() method is called.

For more details on the methods supported by the HttpSession, refer to the HttpServlet API.

This example service() method counts how many times a user has requested the servlet in a session.

    public void service(HttpServletRequest request,
                        HttpServletResponse, response)
                throws IOException
    {
      // Get the session and the counter param attribute
      HttpSession session = request.getSession (true);
      Integer ival = (Integer)
                     session.getAttribute("simplesession.counter");
      if (ival == null) // Initialize the counter
        ival = new Integer (1);
      else // Increment the counter
        ival = new Integer (ival.intValue () + 1);
      // Set the new attribute value in the session
      session.setAttribute("simplesession.counter", ival);
      // Output the HTML page
      out.print("<HTML><body>");
      out.print("<center> You have hit this page ");
      out.print(ival + " times!");
      out.print("</body></html>");
    }

The Lifetime of a Session

A session tracks a user's selections over a series of pages in a single transaction, such as browsing for an item, adding it to a shopping cart, then billing by credit card. A session is transient, and its lifetime ends when:

- a user leaves your site and the user's browser does not accept cookies

- a user quits the browser

- the session is timed out due to no activity

- the session is completed and invalidated by the servlet

- the user logs out and is invalidated by the servlet

For more persistent long term storage of data your servlet should write details to a database using JDBC or EJB and associate the client with this data using a long-lived cookie and/or username and password. Although this document describes that sessions use cookies and persistence internally, you should not use sessions as a general mechanism for storing data about a user.

How Session Tracking Works

How does WebLogic Server know which session is associated with each client? When an HttpSession is created in a servlet, it is associated with a unique ID. The browser must provide this session ID with its request in order for the server to find the session data again. The server attempts to store this ID by setting a cookie on the client. Each time the client sends a request to the server from then onwards, it includes the cookie containing the ID. The server automatically parses the cookie, and supplies the session data when your servlet calls the getSession() method.

If the client does not accept cookies, the only alternative is to encode the ID into the URL links in the pages sent back to the client. For this reason, always use the encodeURL() method when you include URLs in your servlet response. WebLogic Server knows whether the browser accepts cookies and will not unnecessarily encode URLs. WebLogic automatically parses the session ID from an encoded URL, and retrieves the correct session data when you call the getSession() method. Using the encodeURL() method ensures no disruption to your servlet code regardless of the procedure used to track sessions. For more information, see Using URL Rewriting.

Detecting the Start of a Session

After you obtain a session using the getSession(true) method, you can tell if the session has just been created by calling the HttpSession.isNew() method. If this method returns true, then the client does not already have a valid session, and at this point is unaware of the new session. The client will not become aware of the new session until a reply is posted back from the server.

Design your application to accommodate new or existing sessions in a way that suits your business logic. For example, your application might redirect the client's URL to a login/password page if you determine that the session hasn't yet started. Here is a code example:

      HttpSession session = request.getSession(true);
      if (session.isNew()) {
        response.sendRedirect(welcomeURL);
      }

On the login page, provide an option to log in to the system or create a new account.

Setting and Getting Session Name/Value Attributes

You can store data in an HttpSession object using name/value pairs. Data stored in a session is available through the session. Use these methods from the HttpSession interface:

      getAttribute()
      getAttributeNames()
      setAttribute()
      removeAttribute()

The following code fragment shows how to get all of the existing name/value pairs:

      Enumeration sessionNames = session.getAttributeNames();
      String sessionName = null;
      Object sessionValue = null;

      whlie (sessionNames.hasMoreElements()) {
        sessionName = (String)sessionNames.nextElement();
        sessionValue = session.getAttribute(sessionName);
        System.out.println("Session name is " + sessionName +
                    ", value is " + sessionValue);
      }

To add or overwrite a named attribute, you use the setAttribute() method. To remove a named attribute altogether, use the removeAttribute() method.

Note: You can add any Java descendant of Object as a session attribute and associate it with a name. However, if you are using session persistence, your attribute "value"
objects must implement java.io.Serializable.

ClassCastException and HTTP Sessions

You might encounter a ClassCastException while developing servlets that use HTTP sessions. This could happen as a result of the following set of events:

1. You store a reference to a custom class, myFoo, in an HTTP session.

2. While in mid-session, you change your servlet (or JSP or JHTML), causing it to be reloaded. In fact, it is necessary for it to be reloaded by a completely new class loader, and the old class loader that had previously loaded it must be discarded.

3. Because your custom class myFoo is also located under the servlet classpath, it too is reloaded by the new class loader.

4. Now, when you retrieve myFoo from the HTTP session, you cast it to the expected type, but you recieve a ClassCastException. The exception is thrown even if class myFoo has not changed. Because it has been loaded by a different class loader, it is regarded by the JVM as incompatible.

   Note: If you are using session persistence, the class contents must be serialized, and you will not encounter this exception.

Here are some suggested work-arounds to this problem:

- Do not place your class myFoo in the servlet classpath. Instead, place it in the system classpath or the weblogic.class.path, which are accessible by WebLogic Server. The class will not be reloaded when the servlet is modified. This drawback to this solution is that you cannot prototype the myFoo class, because you must restart the server in order to reload the class after it is modified.

- If you need to prototype the class, you can write a wrapper method within it to store and retrieve its contents to and from the session. You do not access the class directly from the session, but instead call it is wrapper methods to store or populate it is contents from the session. As long as you use standard Java class types to store the class contents, they will not be reloaded when the servlet is reloaded. This approach has performance drawbacks because your wrapper methods would need to set or get multiple name=value pairs for each class's attributes.

- Another work-around is to catch the ClassCastException, and replace the old class that is stored in the session with a newly instantiated class, or remove it from the session. Unfortunately, you lose the session data that was previously stored in the class, so you must write your application to handle this scenario. This is the easiest solution to the problem-remember that you should not be storing critical information in an HTTP session, but rather storing it in a database.

You may also get a ClassCastException using JavaBeans with Servlets. The servlet puts the JavaBean in the session and the JSP gets that JavaBean from the session. When the Bean class is in the WebLogic Classpath (/myserver/serverclasses) and the Bean's source code is in that same directory, you will encounter a ClassCastException .

Note: The ClassCastException generally occurs while you are developing your servlets, and should not be an issue in a stable production system. If you are upgrading your system online, you might wish to warn your customer base.

Logging Out and Ending a Session

If your application deals with sensitive information you might consider offering the ability to log out of the session. This is a common feature with shopping carts and Internet email accounts. When the same browser returns to the service, the user must log back into the system. To achieve this, you can invalidate the current session by calling:

    session.invalidate()

Do not reference an invalidated session after you have called this method. If you do, an IllegalStateException will be thrown. The next time a user visits your servlet from the same browser, the session data will be missing, and a new session will be created when the getSession(true) method. At this point you might want to send the user to the login page again.

Configuring Session Tracking

WebLogic Server provides many configurable properties that determine how WebLogic Server handles session tracking. For details on configuring these session tracking properties, see the Administrators Guide, Setting up session management.

Using URL Rewriting

In some situations, a browser may not accept cookies, which makes session tracking using cookies impossible. URL rewriting is a work-around to this scenario that can be substituted automatically when WebLogic Server detects that the browser does not accept cookies. URL rewriting involves encoding the session ID into the hyper-links on the Web pages that your servlet sends back to the browser. When the user subsequently clicks these links, WebLogic Server extracts the ID from the URL address and finds the appropriate HttpSession when your servlet calls the getSession() method.

To enable URL rewriting in WebLogic Server, you must set the following property in your weblogic.properties file:

      weblogic.httpd.session.URLRewriting.enable=true

Note that in order to preserve authenticated status when using weblogic.serlvet.security.ServletAuthentication, WebLogic checks the status of the HttpSession from the request. If weblogic.httpd.session.URLRewriting.enable is true this causes the post data to be consumed. So, if you intend to send post data to the server and you expect to be able to read the raw post data, you should set the content type to something other than the default value of application/x-www-form-urlencoded.

There are some general guidelines for how your code should handle URLs in order to support URL rewriting. You should avoid writing a URL straight to the output stream, as shown here:

    out.println("<a href=\"/myshop/catalog.jsp\">catalog</a>");

Instead, use the HttpServletResponse.encodeURL() method instead, For example:

    out.println("<a href=\""
         + response.encodeURL("myshop/catalog.jsp")
         + "\">catalog</a>");

Calling the encodeURL() method determines if the URL needs to be rewritten, and if so, it rewrites it, by including the session ID in the URL.

In addition to URLs that are returned as a response to WebLogic Server, also encode URLs that send redirects. For example:

      if (session.isNew())
        response.sendRedirect (response.encodeRedirectUrl(welcomeURL));

WebLogic Server will use URL rewriting when a session is new, even if the browser does accept cookies, because the server cannot tell if a browser accepts cookies in the first visit of a session.

Your servlet may determine if a given session was determined from a cookie by checking the boolean returned from the HttpServletRequest.isRequestedSessionIdFromCookie() method. Your application may respond appropriately, or simply rely on URL rewriting by WebLogic Server.

URL rewriting and Wireless Access Protocol (WAP)

If you are writing a WAP application, you will need to use URL rewriting because the WAP protocol does not support cookies. In addition, some WAP devices have a 128 character limit on the length of a URL (including parameters), which limits the amount of data that can be transmitted using URL re-writing. To allow more space for parameters, you can limit the size of the session ID that is randomly generated by WebLogic Server by specifying the following property in the weblogic.properties file:

weblogic.httpd.session.sessionIDLength=bytes

The minimun value is 8 bytes, the default value is 52 bytes. The maximum value is Integer.MAX_VALUE.

Making Sessions Persistent

You can set up WebLogic Server to record session data in a persistent store. If you are using session persistence, you can expect the following characteristics:

- Good failover, because sessions are saved across server down-time.

- Better load balancing, because any server can better handle requests for any number of sessions, and use caching to optimize performance. See the cacheEntries property for more information, see Configuring session persistence.

- Sessions can be shared across clustered WebLogic Servers. Note that session persistence is no longer a requirement in a WebLogic Cluster. Instead, you can use in-memory replication of state.

- For customers who want the highest in servlet session persistence, JDBC-based persistence is the best choice. For customers who want to sacrifice some amount of session persistence in favor of drastically better performance, in-memory replication is the appropriate choice. JDBC-based persistence is noticeably slower than in-memory replication. In some cases, in-memory replication has outperformed JDBC-based persistence for servlet sessions by a factor of eight.

- It is legal to put any kind of Java object into a session, but for file, JDBC, and in-memory replication only objects that are java.io.Serializable can be stored in a session.

Scenarios To Avoid When Using Sessions

Do not use session persistence for storing long term data between sessions. In other words, do not rely on a session still being active when a client returns to a site at some later date. Instead, your application should record long-term or important information in a database.

Sessions are not a convenience wrapper around cookies. Do not attempt to store long term or limited term client-data in a session. Instead, your application should create and set its own cookies on the browser. Examples include an auto-login feature where the cookie might live for a long period, or an auto-logout feature where the cookie might expire after a short period of time. Here, you should not attempt to use HTTP sessions, but instead write your own application-specific logic.

Use Serializable Attribute Values

When you use persistent sessions, all attribute "value" objects that you add to the session must implement java.io.Serializable. For more details on writing serializable classes, refer to the online java tutorial about serializable objects. If you add your own serializable classes to a persistent session, be careful that each instance variable of your class is also serializable. Otherwise, you can declare it as transient, and WebLogic will not attempt to save that variable to persistent storage. One common example of an instance variable that must be made transient is the HttpSession object. (See the notes on using serialized objects in sessions in the section Making Sessions Persistent )

Configuring Session Persistence

For details on setting up persistent sessions, see the Administrators Guide Setting up WebLogic as an HTTP server: Configuring session persistence.

Using Cookies in a Servlet

A cookie 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 at up to 4k per cookie.

Setting Cookies in an HTTP servlet

To set a cookie on a browser, you 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 adding 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. Setting the setMaxAge to -1, or any other negative value, means that the cookie is not stored persistently and will be deleted when the Web browser exits. Setting setMaxAge to 0 will cause the cookie to be be immediately deleted, setting the cookie's max age to that of the server. Note that this causes the cookie to be immediately invalidated, regardless of any discrepancy in the time on the user's browser. All times are relative to the current time on the server, and thus if the browser's clock is different, this may have undesired effects.

Because cookies only accept string-type values, you should cast to and from the desired type that you want to store in the cookie. A common practice is to use the handle ID of an EJB instance for the cookie value and store the user's details in the EJB.

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:

    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 needs to 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 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 your are looking for a cookie called "ChocolateChip" that may have been previously set in a browser client. For example:

    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());
    }

For more details on cookies, see The Cookie API and The Java Tutorial: Using Cookies.

Using Cookies that Will Be 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 following property in the weblogic.properties file for the server (or cluster) that hosts the servlet:

    weblogic.httpd.session.cookie.domain=myserver.com

This property will instruct the browser to include the proper cookie(s) for all requests to hosts in the domain specified in place of "myserver.com". For more information on this property or configuring session cookies, see Setting up WebLogic as an HTTP Server.

Your 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 you design your application, 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, a user may not want to leave an automatic login for their account. Do not assume that a user knows what a cookie is; instead ask a question like:

  Automatically login from this computer?

- Always ask for a password to log on for sensitive data-unless the 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.

Using WebLogic Services from an HTTP Servlet

If you write a browser client using server-side Java, your client has access to many of the rich features of WebLogic Server such as factory methods-like JNDI, RMI, EJB, JDBC connections, etc.-as a WebLogic server-side process, rather than as a Java client application. You can do this with a static method from the weblogic.common.T3Services class, as shown here:

     T3ServicesDef t3s =
        T3Services.getT3Services();

Once you have a T3ServicesDef object, you can call any of the factory methods from that interface to get access to WebLogic services. For example, here is how you might submit an event registration from a servlet (where request is the HttpServletRequest object):

    ParamSet eventParameters = new ParamSet();
    String name;
    Enumeration names = request.getHeaderNames();
    while (names.hasMoreElements()) {
      name = (String)names.nextElement();
      try {
        eventParameters.setParam(name, request.getHeader(name));
      }
      catch (Exception e) {;}
    }
    EventMessageDef ev = T3Services.getT3Services().events()
     .getEventMessage("HTTPWATCH", eventParameters);
    ev.submit();

Here is another example of how you might use WebLogic services from a servlet, through the log() and config() services:

    T3ServicesDef t3s = T3Services.getT3Services();
    String consoleEnabled =
      t3s.config().getProperty("weblogic.system.enableConsole");
    String logmsg = "Console enabled was set to " +
                    consoleEnabled + " at " +
                    new java.util.Date();
    LogServicesDef logger = t3s.log();
    logger.log(logmsg);

Accessing Databases-Using Connection Pools in a Servlet

WebLogic Server supports the use of JDBC connection pools from server-side Java classes, including servlets, using two server-side JDBC drivers: one for routine use for most database operations, and another for transactional operations such as Enterprise JavaBeans (EJB). Because WebLogic Server's servlet persistence is EJB-based, connection pools are used as part of your configuration setup for persistence.

A connection pool is a named group of identical JDBC connections to a database that are created when the connection pool is registered, usually when starting up WebLogic Server. Your servlets "borrow" a connection from the pool, use it, then return it to the pool by closing it. This is far more efficient than creating a new connection for each client each time they need to access the database. Another advantage is that you do not need to hard-code details about the database your application uses.

WebLogic supplies special JDBC "pool" drivers that give server-side Java access to connection pools that are registered on WebLogic Server.

WebLogic's JDBC pool drivers include:

- Pool driver for most server-side operations:

Driver URL: jdbc:weblogic:pool
Driver package name: weblogic.jdbc.pool.Driver

This driver, which is most often used with servlets, is documented here.

- JTS pool driver:

Driver URL: jdbc:weblogic:jts
Driver package name: weblogic.jdbc.jts.Driver

For more about using the JTS-based JDBC pool driver for EJBeans, read The WebLogic EJB Environment and Using the JTS Driver.

Setting up the Registration for a Connection Pool

To configure a connection pool, you add a registration for it to the weblogic.properties file. The connection pool is created each time you start WebLogic Server and exists until the server is shut down. There are more details on setting properties for JDBC connection pools in the document Creating and Using Connection Pools.

You configure most aspects of the connection pool from the properties file, such as:

- Username and password access control list (ACL) for connecting to your database

- The name of the connection pool

- The size of the connection pool, and how it should grow on demand

It is easy to use a connection from the pool in your servlet code. Your servlet code is abstracted from administration details of the pool. You can configure the pool, or even point the named connection pool at a completely different database, all without changing or recompiling any code.

The following example of a registration from a weblogic.properties file is for a connection pool named sales and its ACL (the ACL is specified with the property weblogic.allow.reserve.weblgoic.jdbc.connectionPool.sales). This pool uses WebLogic jDriver for Oracle to connect to an Oracle database.

    weblogic.jdbc.connectionPool.sales=\
       url=jdbc:weblogic:oracle,\
       driver=weblogic.jdbc.oci.Driver,\
       initialCapacity=2,\
       maxCapacity=10,\
       capacityIncrement=2,\
       props=user=scott;password=tiger;server=goldengate

    weblogic.allow.reserve.weblogic.jdbc.connectionPool.sales=\
       joeuser,maryuser

If you do not set an ACL for a connection pool, or one is not provided by the context of your code (such as the properties of a t3 Client), it defaults to "everyone"-that means any user can grab a connection. If you want to restrict access to the pool to certain users:

1. Set up an ACL in the weblogic.properties file. For example:

       weblogic.allow.reserve.weblogic.jdbc.connectionPool.sales=\
          joeuser,maryuser

2. Set up a username and password for each application user with a java.util.Properties object in your code. For example:

       Properties props = Properties();
             props.set("user",            "joeuser");
             props.set("password",        "dP3m*spQc!");

3. Pass the properties object to the connection object that represents the connection to the pool. For example:

       Driver myDriver = (Driver) Class.forName
           ("weblogic.jdbc.pool.Driver").newInstance();
       conn =  myDriver.connect("jdbc:weblogic:pool:sales",props);

   Note that this username and password is the valid username and password that matches a user registered in the weblogic.properties file, and not a database username and password. At runtime, the username and password supplied by the application is checked against the list of T3Users established in the access control list for the connection pool.

4. Assign each of the users in the ACL a password in the weblogic.properties file, as shown here:

       weblogic.password.joeuser=dP3m*spQc!

Using a Connection Pool in a Servlet

Here is a simple servlet that selects all of the records from a database table using dbKona (a proprietary BEA API that creates high-level abstractions for database operations), and displays them using htmlKona (a BEA proprietary API for creating HTML in Java code).

1. Load the pool driver and cast it to java.sql.Driver. The full pathname of the driver is weblogic.jdbc.pool.Driver. For example:

       Driver myDriver = (Driver)
          Class.forName("weblogic.jdbc.pool.Driver").newInstance();

2. Create the connection with the URL for the driver, plus (optionally) the name of the registered connection pool. The URL of the pool driver is jdbc:weblogic:pool.

   You can identify the pool in one of two ways:

   - Add the name of the pool to the end of the URL. In that case you will not need a Properties object unless you are setting a username and password for use of a connection from the pool. If you do not set the username and password for a t3user in a Properties object, the username defaults to "guest". If you have registered an ACL in the weblogic.properties file, you must include example:

         Connection conn =
            myDriver.connect("jdbc:weblogic:pool:sales", null);

   - Specify the name of the connection pool in a java.util.Properties object using the key connectionPoolID. For example:

         Properties props = new Properties();
         props.put("connectionPoolID", "myConnectionPool");
         Connection conn =
           myDriver.connect("jdbc:weblogic:pool", props);

     Note that the Driver.connect() method is used in these examples instead of the DriverManger.getConnection() method. Although you may use DriverManger.getConnection() to obtain a database connection, BEA recommends that you use Driver.connect() because this method is not synchronized and provides better performance.

     Note that the Connection returned by connect() is an instance of weblogic.jdbc.pool.Connection.

3. Call the close() method on the Connection object when you have finished with your JDBC calls, so that the connection is properly returned to the pool. A good coding practice is to create the connection in a try block and then close the connection in a finally block, to make sure the connection is closed in all cases. (See the complete code example below for and example.)

Here is the code for the entire servlet. This servlet displays the contents of the "emp" database table in an HTML table on a Web page:

Listing 4-1 simpleselect.java

    package examples.jdbc.pool;

    import java.io.*;
    import java.sql.*;
    import java.util.Properties
    import javax.servlet.*;
    import javax.servlet.http.*;
    import weblogic.db.jdbc.*;
    import weblogic.html.*;

    public class simpleselect extends HttpServlet {

      public synchronized void service(HttpServletRequest req,
                                       HttpServletResponse res)
        throws IOException
      {
        Connection conn = null;
        try {

          Properties props = Properties();
          props.set("user",            "joeuser");
          props.set("password",        "dP3m*spQc!");

          Driver myDriver = (Driver) Class.forName
              ("weblogic.jdbc.pool.Driver").newInstance();
          conn =  myDriver.connect("jdbc:weblogic:pool:sales",props);

          res.setStatus(HttpServletResponse.SC_OK);
          res.setContentType("text/html");

          TableDataSet ds = new TableDataSet(conn, "emp");
          TableElement tbl = new TableElement(ds);

          ServletPage hp = new ServletPage("Simple select");
          hp.getBody()
            .addElement(MarkupElement.HorizontalLine)
            .addElement(tbl);

          ds.close();
          conn.close();
          hp.output(res.getOutputStream());
        }

        catch (Exception e) {
          ServletPage hp =
            new ServletPage("An Exception occurred");
          ByteArrayOutputStream ostr =
            new ByteArrayOutputStream();
          e.printStackTrace(new PrintStream(ostr));
          hp.getBody()
            .addElement(new
              HeadingElement("An Exception occurred:", 2))
            .addElement(new LiteralElement(ostr.toString()));
          hp.output(res.getOutputStream());
        }
        finally {
          conn.close();
        }
      }
    }

The htmlKona class TableElement automatically generates a formatted HTML table from a TableDataSet.

This example may be compiled and run from the distribution directory examples/jdbc/pool.

Threading Issues in HTTP Servlets

When you design a servlet, 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. The following tips will help you to design around this issue.

As of the WebLogic 4.5 release, the SingleThreadModel is supported, as specified in the JSDK2.1. An instance of a class that implements the SingleThreadModel is guaranteed not to be invoked by multiple threads simultaneously. Multiple instances of a SingleThreadModel servlet are used to service simultaneous requests, each running in a single thread.

To efficiently use the SingleThreadModel, WebLogic Server creates a pool of servlet instances for each servlet that implements SingleThreadModel. WebLogic Server creates the pool of servlet instances when the first request is made to the servlet and increments the number of servlet instances in the pool as needed.

When designing your servlet, consider how you use shared resources outside of the servlet class such as file and database access. Because there will be multiple instances of servlets that are identical, and may use exactly the same resources, there are still synchronization and sharing issues that must be resolved, even if you do implement the SingleThreadModel. For instance, the SurveyServlet example (distributed with the JSDK) writes to a file and the SingleThreadModel will not protect against multiple servlet instances writing to the same file.

BEA recommends that shared resource issues be handled by the developer on an individual servlet basis. Consider the following guidelines:

- Wherever possible, avoid synchronization, because it will cause subsequent servlet requests to bottle-neck until the current thread has completed.

- 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.

Passing the Request to Another HTTP Servlet

When a servlet is requested, the servlet can conditionally pass that request on to be handled by another servlet. This process is sometimes referred to as "servlet chaining". A common use of servlet chaining is where the application requires that the user be logged in before performing a certain function. If the servlet is requested and the user is not logged in, the request is redirected to a login servlet. A token might be saved in the HTTP session to note where the original request was made so that control can return there after a successful login.

A servlet passes a request to another servlet using the RequestDispatcher. This avoids the need to send an HTTP-redirect response back to the client. The RequestDispatcher correctly passes the HTTP request to the HTTP servlet it represents. To obtain the appropriate RequestDispatcher for a particular HTTP servlet, use one of the following methods from the ServletContext, which your servlet may access via the call:

      ServletContext sc = getServletConfig().getServletContext();

Your servlet can look up the RequestDispatcher for a servlet using one of these methods:

ServletContext.getRequestDispatcher(String path)
  Where path is the URL that the requested servlet handles for this servlet context. For example, a path of "/login" might obtain a RequestDispatcher for a servlet registered to handler requests to "/login". The returned RequestDispatcher can then be used to forward the request to the login servlet.

ServletContext.getNamedDispatcher(String name)
  Where name is the name assigned to the servlet in a Web Application deployment descriptor. You must deploy your servlets in a Web Application to use this method. For more details, see the Developers Guide Writing a Web Application. This method is advantageous because the servlet URL is separated from the servlet name in your servlet code. The Web Application deployment descriptor also makes this distinction between servlets and servlet-mappings.

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 "/" it is interpreted to be relative to the servlet context.
  The returned RequestDispatcher object can then be used to forward the request to another servlet.

The RequestDispatcher has two methods that allow you either to forward the entire servlet request to a servlet, or include the output from another servlet in your servlet's response. These methods are discussed in the next two sections.

You can obtain a RequestDispatcher for any HTTP resource within a context, including HTTP Servlets, JSP pages, or plain HTML pages. Simply request the appropriate URL path for the resource in the getRequestDispatcher() method.

Forwarding a Request

Once you have the correct RequestDispatcher, your servlet forwards a request using the RequestDispatcher.forward() method, passing the HTTPServletRequest and HTTPServletResponse as arguments.

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 prior to forwarding the request, an IllegalStateException will be thrown.

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

Including a Request

Your servlet can include the output from another resource by using the RequestDispatcher.include() method, and passing the HTTPServletRequest and HTTPServletResponse as arguments.

Any attempt to set the response status code, or any HTTP header information from the included servlet response is ignored. In effect, you can use this method to achieve a server-side-include of another HTTP resource from your servlet code.

Using Server-Side Includes

Note: Note: It is recommend that you use JavaServer Pages and the JSP include directive to achieve the same effect as Server-Side Includes in WebLogic Server. With JSPs, you can write plain HTML into a JSP page without using the more sophisticated features of JSP. JSP allows you to include data in a JSP page in two ways; these procedures are described concisely in section 2.7 of the JSP specification. For more details, please see the Developers Guide Using WebLogic JSP.

Server-side includes are scheduled for deprecation in a future release of WebLogic Server.

WebLogic supports a subset of server-side includes (.shtml files) that uses an internal WebLogic servlet called the ServerSideIncludeServlet. Server-side includes allow you to incorporate templates in your HTML pages. You can define the templates in separate files, and then include them in other Web pages to make maintenance easier. For example, you might define a header and a footer for all of your Web pages. When you want to change the headers, you can make the change in the single template file to take effect on all other pages that include the template file.

You may also invoke a servlet using the servlet tag to generate dynamic content within your Web page, although for new projects we recommend you consider using JSP.

HTML files containing server-side includes traditionally have an .shtml extension. The ServerSideIncludeServlet is registered in the weblogic.properties file to handle all requests for files with this extension. Like the FileServlet, the ServerSideIncludeServlet searches for files below the document root. For details on setting up the ServerSideIncludeServlet, see Using server-side includes.

WebLogic supports two Server-side include directives:

- The #include directive allows you to incorporate another file within the page that contains the directive. WebLogic Server embeds the included file in the page that is sent back to the browser. For example:

      <!--#include virtual=filename-->

  Note: Note: WebLogic only implements the virtual tag from the NCSA specification, where virtual gives a file that is relative to the document root. Currently, the included files are not interpreted for sub-ServerSideInclude directives.

- The <servlet> tag causes WebLogic Server to invoke a named servlet when the page is requested. The servlet might perform a specific task, or provide some dynamic content in the page.

  To use the <servlet> tag, set the name attribute to the virtual name of the registered servlet (for more about registering servlets for use with WebLogic, read Setting up WebLogic as an HTTP server). For example:

      <servlet name=servletVirtualName>
        <param name=paramName value=paramValue>
      </servlet>

  Note: Note: Due to limitations in the HTTP specification, your embedded servlet may not set header information in the page response. This includes setting cookie data to be sent back to the client.

Administration and Configuration

The required steps for deploying servlets in a production environment differ form those used in a development environment. Deployment in a development environment can be done in a less secure, but more functional environment suitable for testing and debugging. Deployment methods for development environments include using the ServletServlet and the WebLogic Console to deploy your servlet.

Deploying a servlet in a production environment requires registering the servlet in the weblogic.properties file and setting various parameters that tune the servlet's performance. There are also several options for securing access to your servlet. All of these options are discussed in this section.

Setting up ACLs for Servlets in the WebLogic Realm

Note: Note: Although you may use the methodology described below to set up ACLs for your servlets, BEA recommends instead that you define security for your servlets by incorporating your servlet into a web application. ACLs for a web application are defined using a deployment descriptor. This procedure is described in Writing a Web Application

WebLogic Server controls access to internal resources like HTTP servlets through access control lists (ACLs) that are set up in the WebLogic Realm. Entries for ACLs in the WebLogic Realm are listed as properties in the weblogic.properties file. (For more info on the properties file, see the WebLogic Administrators Guide, Setting WebLogic properties.

You can set the execute permission for an HTTP servlet by adding a property to the weblogic.properties file. The ACL named weblogic.servlet controls access to all registered servlets. Setting the execute permission for the weblogic.servlet ACL to everyone allows anyone to execute any servlet without entering a password, except those servlets with more specific ACLs.

To limit access to an individual servlet, set its execute permission to a list of one or more users. For example, setting the weblogic.servlet.AdminProperties ACL to the user system allows general access (without a password) to all registered servlets except AdminProperties; only the system user would be able to execute that servlet. (The user "system" always has access to all servlets, but in this case setting the permission for this servlet effectively denies permission to everyone else.) For example:

    weblogic.allow.execute.weblogic.servlet=everyone
    weblogic.allow.execute.weblogic.servlet.AdminProperties=system

Setting ACLs for Groups of Servlets

You can organize servlets into groups using a delimited virtual name, then set a single ACL for those virtual names. The example below registers all administration servlets against the virtual name pattern Admin.xxxx. One ACL is set to allow access to all servlets, and another ACL to limits access to all servlets beginning with the virtual name pattern Admin. The second ACL is more specific than the first, so it effectively limits administration abilities to the system user.

      weblogic.httpd.register.Admin.events=admin.AdminEvents
      weblogic.httpd.register.Admin.clients=admin.AdminClients
      weblogic.httpd.register.Admin.connections=\
              admin.AdminConnections
      weblogic.httpd.register.Admin.jdbc=admin.AdminJDBC
      weblogic.httpd.register.Admin.license=admin.AdminLicense
      weblogic.httpd.register.Admin.main=admin.AdminMain
      weblogic.httpd.register.Admin.props=admin.AdminProps
      weblogic.httpd.register.Admin.threads=admin.AdminThreads
      weblogic.httpd.register.Admin.version=admin.AdminVersion

      # Allow anyone to execute registered servlets
      weblogic.allow.execute.weblogic.servlet=everyone
      # Allow only 'system' to execute any 'Admin' servlets
      weblogic.allow.execute.weblogic.servlet.Admin=system

Note: The following property has been deprecated:

    weblogic.httpd.requireAuthentication=false

Its equivalent property is:

      weblogic.allow.execute.weblogic.servlet=everyone

It is recommended that you upgrade your weblogic.properties file immediately, because it is not possible to guarantee how long deprecated properties will be supported.

Using the ServletServlet -- a Developer's Shortcut

As you develop servlets, you may find the ServletServlet useful for prototyping. The ServletServlet allows you to invoke servlets that are not registered in the weblogic.properties file.

To use the ServletServlet, you must register it in the weblogic.properties file with the following line:

    weblogic.httpd.register.servlet=\
      weblogic.servlet.ServletServlet

You may find it easier to use if you set a permissive ACL (access control list) on the ServletServlet using:

    weblogic.allow.execute.weblogic.servlet.ServletServlet=\
      everyone

Now you can invoke the ServletServlet from an HTTP request to serve another servlet. You specify the non-registered servlet by its full package name, which is given as the PATH_INFO to the ServletServlet. The PATH_INFO is the remainder of the URL used to reference the servlet. For instance, to invoke the HelloWorldServlet from the ServletServlet, you would use (entered on one line):

    http://localhost:7001/servlet/examples/servlets/
      HelloWorldServlet

The ServletServlet parses the PATH_INFO, and attempts to match it to a given class in the system CLASSPATH of WebLogic Server or in the servlet classpath, where the slash ("/") is interpreted as a dot (".").

If a class does not match the full PATH_INFO name, WebLogic Server tries to match a class to the next least specific classname by truncating the last "/xxxx" from the PATH_INFO, and so on until a matching class name is found. The surplus PATH_INFO is passed on in turn to the matching class. If no matching class is found, a server error is reported.

Warning: A servlet called using the ServletServlet will behave like any other servlet in that the init() method is executed the first time the servlet is called. (Versions of WebLogic Server prior to version 5.1 re-initialized a servlet called from the ServletServlet each time the servlet was called.)

Also, once the servlet class is loaded, it is not loaded again when subsequent servlet objects are instantiated. If you want WebLogic Server to use your latest servlet class files during runtime, you must use the servlet classpath, as described in the Using the Servlet Classpath

Disadvantages of Using the ServletServlet

In some special cases, you may need to use the ServletServlet as the mechanism for delivering servlets in a production release site. However, be aware that using the ServletServlet has the following disadvantage:

The ServletServlet does not administer WebLogic Server security access control over the servlets is serves. Users with permission to invoke the ServletServlet may use it to invoke any servlet on the host, including unregistered servlets. This counteracts any ACLs you have on other servlets in your system, and poses a security risk. You may also invoke a specific servlet to serve types of files that should otherwise be served by a more appropriate servlet.

For example, if you register the ServletServlet under the virtual name servlets, you can use that virtual name to call any servlet class file. A URL request to

    http://host/servlets/weblogic/FileServlet/index.jsp

calls upon the weblogic.FileServlet servlet class to serve the source code of index.jsp as a plain HTML file, perhaps exposing code you would prefer to keep confidential.

For these reasons, WebLogic does not recommend the use of the ServletServlet in a production system unless there is a special circumstance that explicitly requires it.

Using the Servlet Classpath

Servlet classes placed in the servlet classpath are dynamically reloaded when they are modified. WebLogic Server can be configured to check for updates periodically, or whenever a class is invoked.

You can use the servlet classpath to redeploy your HTTP servlets at runtime, as they are updated, without the need to restart WebLogic Server. Classes that are referenced by JSP or JHTML pages are also reloaded if located in the servlet classpath.

JSP and JHTML pages are always recompiled if modified. However, the classes they use must be in the servlet classpath if you want them reloaded when they are modified.

To use the reload-on-modify feature, follow these steps:

1. Place your HTTP servlet classes in a directory hierarchy that is outside of the system CLASSPATH. A standard directory for servlets exists in the default WebLogic Server installation at:

       /weblogic/myserver/servletclasses

   Place your servlet classes under this directory using the -d option in your servlet compile command. If you run the setEnv script provided in the root directory of the WebLogic Server installation, it will set up the environment variable SERVLET_CLASSES to point to this directory. You can use the variable in your compile command, for example:

       $  javac -d %SERVLET_CLASSES% myServlet.java

2. By default, the servlet classpath is set to the directory referenced by %SERVLET_CLASSES% in the weblogic.properties file. Search for this property and uncomment it if necessary:

       weblogic.httpd.servlet.classpath=\
           /weblogic/myserver/servletclasses

   You can add multiple directories to the servlet classpath, just as you would for the Java system classpath, separated by semi-colons ";". Note that in the weblogic.properties file, you use forward slashes "/" on all operating systems.

3. Configure WebLogic Server to check periodically for modified servlet classes by setting the following property in the weblogic.properties file:

         weblogic.httpd.servlet.reloadCheckSecs=x

   where the server checks every x seconds for modified servlet classes. If x is set to zero, the servlet classes are checked every time they are invoked. If x is set to "-1", the servlet classes are never checked (effectively disabling the reload-on-modify feature).

Tips for Using the Servlet Classpath

- Although it is recommended that you use the default %SERVLET_CLASSES% directory as your servlet classpath for all of your servlets, you can use other directories by adding them to the servlet classpath property.

- The servlet classpath should never share directories with other classpaths used by WebLogic Server such as the Java system classpath, and the weblogic.class.path. The behavior is not defined if you place duplicate classes in other classpaths and the servlet classpath, or if you point the servlet classpath to the other classpaths. You may find that the reload-on-modify feature will not work correctly, and it may be confusing to debug your code.

- Servlets in the servlet classpath cannot contain native methods. The Java security model prevents class loaders other than the system class loader from loading classes that contain native code.

- You can reference servlets in the servlet classpath from the ServletServlet. These servlets are also reloaded if modified, as is true for registered servlets.

  Warning: If you store a reference to one of your classes in an HTTP session and that class is loaded from the servlet classpath and if your servlet is reloaded, you will recieve a ClassCastException when you retrieve the object from the HTTP session. See the notes on ClassCastException and HTTP Sessions.

Clustering Servlets

WebLogic supports clustering servlet services across a WebLogic Cluster. Clustering provides failover and load balancing to increase the performance and reliability of your Web site. Provided that you use HTTP sessions as they were intended, there are no servlet implementation differences to consider.

For details on setting up a WebLogic Cluster, including using JDBC session persistence and in-memory state replication with a proxy server, see the Administrator Guide Setting up a WebLogic Cluster: Setting up HTTP servlets.

Copyright © 2000 BEA Systems, Inc. All rights reserved. Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.