Sun Java System Web Server 7.0 Developer's Guide to Java Web Applications

Creating Servlets

To create a servlet, create a class that extends either GenericServlet or HttpServlet, overriding the appropriate methods so that the servlet handles request.

This section discusses the following topics:

Creating the Class Declaration

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

The following example header shows the HTTP servlet declaration called MyServlet:


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

     public class myServlet extends HttpServlet {
        ...servlet methods...
     }

Overriding Methods

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

Overriding init()

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


Note –

When extending GenericServlet or HttpServlet, you must either override init(ServletConfig) to first call super.init(ServletConfig) or simply override the init() method that takes no arguments. This your servlet's ServletConfig enables be saved locally and later returned by calls to your servlet's getServletConfig() method.


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


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

This method enables other servlet methods to access the variable.

Overriding Destroy

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

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


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

Overriding Service, Get, and Post

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

The default service() method in an HTTP servlet routes the request to another method based on the HTTP transfer method (POST, and GET). For example, HTTP POST requests are routed to the doPost() method, HTTP GET requests are routed to the doGet() method. This routing enables the servlet to perform different request data processing depending on the transfer method. Because the routing takes place in service(), you do not need to override service() in an HTTP servlet. Instead, override doGet(), anddoPost() depending on the expected request type.

The automatic routing in an HTTP servlet is based on a call to request.getMethod(), which provides the HTTP transfer method.

Override the service() method for generic servlets or the doGet() or doPost() methods for HTTP servlets to perform tasks needed to answer the request. Very often, these tasks collate the needed information (in the request object or in a JDBC result set object), and then passing the newly generated content to a JSP for formatting and delivery back to the client.

Most operations that involve forms use either a GET or a POST operation, so for most servlets you override either doGet() or doPost(). Implement both methods to provide for both input types or pass the request object to a central processing method, as shown in the following example:


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

All request-by-request traffic in an HTTP servlet is handled in the appropriate doOperation() method, including session management, user authentication, JSP pages, and accessing Sun Java System Web Server 7.0 features.

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

For more information, see Calling a Servlet Programmatically.

Accessing Parameters and Storing Data

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

To access all incoming request parameters, use the getParameter() method, for example:


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

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


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

Handling Sessions and Security

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

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

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

For more information about session objects, see Chapter 6, Session Managers.

Handling Threading Issues

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

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


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

   public class myServlet extends HttpServlet {

   public void doGet (HttpServletRequest request,
                     HttpServletResponse response)
            throws ServletException, IOException {
      //pre-processing
       synchronized (this) {
         //code in this block is thread-safe
      }
      //other processing;
      }

    public synchronized int mySafeMethod (HttpServletRequest request)
      {
      //everything that happens in this method is thread-safe
      }
   }

         

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

   public class myServlet extends HttpServlet
       implements SingleThreadModel {
      servlet methods...
   }

         

Note –

If a servlet is specifically written as a single thread, the servlet engine creates a pool of servlet instances to be used for incoming requests. If a request arrives when all instances are busy, the request is queued until an instance becomes available.


Delivering Client Results

The final user interaction activity is to provide a response page to the client. The response page can be delivered by creating a servlet response page or JSP response page.

Creating a Servlet Response Page

Generate the output page within a servlet by writing to the output stream. The recommended generation method depends on the output type.

Always specify the output MIME type using setContentType() before any output commences, as follows


response.setContentType("text/html");

Creating a JSP Response Page

Servlets can invoke JSP files in two ways, the include() method and the forward() method.


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

Note –

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


This example shows a JSP page using forward():


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

You identify which JSP noun to call by specifying a Universal Resource Identifier (URI). The path is a String describing a path within the ServletContext scope. You can also use the getRequestDispatcher() method in the request object that takes a String argument indicating a complete path.


Note –

Identify


RequestDispatcher dispatcher = req.getRequestDispatcher(“foo/bar”);


Note –

In the previous example getRequestDispatcher does not start with “/”. In Web Server 6.1, this syntax resulted in a URI such as /webapp/foo/bar. In Sun Java System Web Server 7.0, the URI appears as /webapp/current_servlet_path/foo/bar


For more information about JSP pages, see Chapter 5, Developing JavaServer Pages.