Additional Interfaces

 < Free Open Study > 

Finally, the Servlet API to provides two additional interfaces involving servlet threading and request dispatching.

Threading and the SingleThreadModel Interface

Normally, many different client requests may cause the service() method of a servlet to be executed simultaneously (or virtually simultaneously) in different threads for each request.

If the servlet class has class level variables declared, then if the any of the threads executing update the class variable, another thread could end up with inconsistent values for the class variable through the service() method.

There are a number of ways around this, such as synchronizing access to the variables concerned, or moving the variables (if suitable). However synchronization or locking an object has performance implications because any other threads trying to access the synchronized resource will be blocked from execution until the synchronization lock is removed.

An alternative technique is to implement the SingleThreadModel interface in the servlet. This interface defines no methods, so no additional code is required. It is solely used to tag the servlet that implements this, because the servlet container treats servlets that implement this interface differently.

The container effectively guarantees that only one thread will execute concurrently in the servlet's service() method, by synchronizing access to each instance of the servlet.

The servlet may instantiate one or more instances of a servlet implementing this interface and may maintain a pool of servlet instances to process requests to this interface.

See Chapter 11 for more information on synchronization issues.

The RequestDispatcher Interface

The servlet container provides the implementation of the RequestDispatcher interface. We can use the RequestDispatcher in a servlet to forward a request to another resource (servlet, JSP, web page, and so on) once we have inspected, and possibly performed some processing on, the request object.

There are two methods provided by the interface: forward() and include(). Using the forward() method means that you forward the request to another resource and any output in the buffer made before the method call is discarded:

    public void forward(ServletRequest request, ServletResponse response) 

The include() method can be used almost like a Server Side Include (SSI), where the servlet can process the request and include the resource (the servlet or HTML web page output) as part of the page:

    public void include(ServletRequest request, ServletResponse response) 

Now let's have an example of how we might use the RequestDispatcher interface.

Implementing RequestDispatcherServlet

This example servlet demonstrates how we can use the RequestDispatcher interface. The purpose of this servlet is to present a list box with a list of resources (servlets and/or HTML files) available within the web application, and to return information on the requested resource beneath this. The servlet makes use of a Dispatching interface which is used to declare constants corresponding to our previously-developed servlets. Any class that implements this interface has access to the constants as if they were declared in that class.

To use the servlet, you will need to add the source code for the servlet and the interface to the \src\basicServlets directory, compile them, and move the classes to the \classes\basicServlet directory, as with previous examples. The following image shows the servlet at work, displaying the output of the BasicServlet included within the web page. The servlet can be accessed at:


click to expand

The Dispatching Interface

First we will look at the Dispatching interface. This has no methods and is simply used to declare constants that represent our previous servlets:

    package basicServlets;    public interface Dispatching { 

For each servlet we previously developed, we have declared two constants. The first is the mapping for the servlet resource, and the second is the name of the servlet:

      public static final String BASIC_SERVLET =            "servlet/basicServlets.BasicServlet";      public static final String BASIC_SERVLET_NAME = "BasicServlet";      public static final String REQUEST_RESPONSE_SERVLET =            "servlet/basicServlets.RequestResponseServlet";      public static final String REQUEST_RESPONSE_SERVLET_NAME =            "RequestResponseServlet";      public static final String CONTAINER_SERVLET =            "servlet/basicServlets.ContainerServlet";      public static final String CONTAINER_SERVLET_NAME =            "ContainerServlet";      public static final String REQUEST_DISPATCHER_SERVLET_PACKAGE =            "basicServlets.RequestDispatcherServlet";      public static final String REQUEST_DISPATCHER_SERVLET_NAME =            "RequestDispatcherServlet"; 

We also include the application index page, to demonstrate that our dispatcher can also use static HTML files as well as servlets:

      public static final String INDEX_HTML = "index.html";      public static final String INDEX_HTML_NAME = "Index Page"; 

Finally we create two String arrays of the servlets/resources paths and names for use in our RequestDispatcherServlet:


The RequestDispatcherServlet Class

Our RequestDispatcherServlet class implements our Dispatching interface in order to access the constants defined in it:

    import;    import;    import java.util.Enumeration;    import javax.servlet.*;    import javax.servlet.http.*;    public class RequestDispatcherServlet                               extends GenericServlet implements Dispatching {      private static StringBuffer form = new StringBuffer();      public void service(ServletRequest request, ServletResponse response)                                         throws ServletException, IOException { 

The start of the servlet code is fairly standard; we access the PrintWriter object and retrieve the servlet parameter indicating which servlet is required:

        ServletContext servletContext = getServletContext();        ServletConfig config = getServletConfig();        PrintWriter out = response.getWriter();        String servletRequested = request.getParameter("servlet"); 

Next we access the RequestDispatcher object for the desired servlet. This enables us to use the include() method to get access to its content on our servlet page. We are using the relative path and this may include other servlets, JSP pages, and HTML files:

        RequestDispatcher requestDispatcher =          servletContext.getRequestDispatcher("/" + servletRequested);        response.setContentType("text/html");        out.println(getPageTitle(servletRequested)); 

We then include the requested resource in our page. This means that the output from the servlet or web page is included as part of our web page.

Before we do this, we also attach an attribute to the request. In the RequestResponseServlet we check at one point if the response was committed. Since we have already output from this servlet, the response.isCommitted() method may return an incorrect result as it is unaware of being included in this servlet's output. Therefore we attach an attribute to the request that serves as an indicator to the RequestResponseServlet that we have already started output, and the response.isCommitted() method may return an incorrect result. This is why, in the RequestResponseServlet, we checked for an attribute set:

        if (requestDispatcher != null) {          request.setAttribute("buffer", "written");          requestDispatcher.include(request, response);        } else if (servletRequested == null) {          out.println("Please chose a servlet");        } else {          out.println(servletRequested + " is not recognised by the server");        }        out.println("</body></html>");        out.flush();      } 

The init() method initializes the form StringBuffer object that, because it is unchanging, need only be initialized once:

      public void init() throws ServletException {        form.append(getForm());      } 

The getPageTitle() method is used to build the head of the HTML page that appears above the included resource:

      private StringBuffer getPageTitle(String servletRequested) {        StringBuffer sb = new StringBuffer();        sb.append("<html><head><title>");        if (servletRequested == null) {          sb.append("[no servlet requested]");        } else {          sb.append(servletRequested);        }        sb.append("</title></head><body><h1><code>");        if (servletRequested == null) {          sb.append("[no servlet was requested]</code>");        } else {            sb.append(servletRequested).append("</code> is shown below");        }        sb.append("</h1><p>");        sb.append(form);        sb.append("<hr width=100%>");        return sb;      } 

The getForm() method sets up the HTML form. It accesses the constants from the Dispatching interface that contain the resources that the dispatcher object may be directed to:

      private StringBuffer getForm() {        StringBuffer sb = new StringBuffer();        ServletConfig config = getServletConfig();        sb.append("<form method=get action=\"" +                   REQUEST_DISPATCHER_SERVLET_PACKAGE + "\">");        sb.append("<table><tr><td>Please choose servlet ");        sb.append("(or other resource) to view:</td>");        sb.append("<td><select name=\"servlet\">");        for (int i = 0; i < RESOURCES.length ; i++) {          sb.append("<option value=\"" + RESOURCES[i] + "\" >" +                    RESOURCES_NAMES[i]);        }        sb.append("</select></td></tr><tr><td colspan=2 align=\"center\">");        sb.append("<input type=\"submit\" ");        sb.append("value=\"View Servlet/Resource\"></td></tr>");        sb.append("</table></form> ");        return sb;      }    } 

 < Free Open Study > 

Professional Java Servlets 2.3
Professional Java Servlets 2.3
ISBN: 186100561X
EAN: 2147483647
Year: 2006
Pages: 130 © 2008-2017.
If you may any questions please contact us: