Servlets

On the server side, we’re not ready to accept an XML-RPC or SOAP request yet because that would require parsing an input XML document. I’ll take that up beginning in a couple of chapters. However, we are completely ready to respond to a CGI request with an XML document. Since this is a book about Java, I’ll use servlets to do this. The user will connect to a known URL. The query string component will include a field asking for a certain number of Fibonacci numbers. The servlet will calculate that number and return it as an XML document with an attached stylesheet.

The query string will include a single generations field whose value is the index of the last Fibonacci number you want. For example, if the servlet is installed at http://www.elharo.com/fibonacci, then you’d ask for 42 Fibonacci numbers by loading the URL http://www.elharo.com/fibonacci?generations=42.

The servlet engine handles the HTTP header and all other interactions with the client. If you need to change any of the details, you use the HttpServletRequest and HttpServletResponse objects passed as arguments to the doGet() method (for HTTP GET) or doPost() (for HTTP POST). This example behaves the same for both POST and GET, so the doPost() method will just call the doGet() method.

For input, it’s easy to read the query string field from a servlet using the getParameter(), getParameterNames(), and getParameterValues() methods. These handle all necessary decoding of x-www-form-urlencoded values. If there’s more than one field in the query string with the specified name, then getParameter() returns the value of the first one. getParameterValues() returns an array of all the field values of fields with a certain name. In this case, I’ll be satisfied with just the first field named generations so I’ll choose getParameter(). Because the getParameter() method effectively hides whether the query string was included in the URL sent by the GET method or in the body sent by the POST method, adding support for POST to this servlet is very easy; simply implement the doPost() method and pass its argument to the doGet() method.

For output, we just need to set the content type to text/xml and write the response on the PrintWriter returned by the HttpServletResponse’s getWriter() method. By default, this PrintWriter uses the ISO-8859-1 encoding. However, if you want to use another encoding such as UTF-8, you must adjust the MIME type to reflect that. For instance, to send data in UTF-16, you set the MIME type to text/xml; charset=UTF-16. Example 3.12 shows the completed servlet.

Example 3.12. A servlet that generates XML

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


public class FibonacciServlet extends HttpServlet {

  public void doGet(
   HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
    
    //read the query string
    int numberOfGenerations = 10;
    String generations = request.getParameter("generations");
    try {
      numberOfGenerations = Integer.parseInt(generations);
    }
    catch (Exception e) { // NumberFormat or NullPointerException
      // use default value of 10 
    }
     
    response.setContentType("text/xml; charset=UTF-8");               
    PrintWriter out = response.getWriter();
    
    out.println("<?xml version=\"1.0\"?>");  
    out.print  ("<?xml-stylesheet ");
    out.println(
     "type='text/css' href='/xml/styles/fibonacci.css'?>");  
    out.println("<Fibonacci_Numbers>"); 
     
    BigInteger low  = BigInteger.ONE;
    BigInteger high = BigInteger.ONE;      
    for (int i = 1; i <= numberOfGenerations; i++) {
      out.print("  <fibonacci index=\"" + i + "\">");
      out.print(low);
      out.println("</fibonacci>");
      
      BigInteger temp = high;
      high = high.add(low);
      low = temp;
    }
    out.println("</Fibonacci_Numbers>");  
        
    out.close();
    
  }

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

}

Once you’ve compiled this servlet, you’ll need to install it on your server. Details vary a little from servlet engine to servlet engine. I use the Apache Jakarta Project’s Tomcat, which is the official reference implementation of the Java Servlet API. If you’re using something different, please consult your local documentation.

To install the servlet into Tomcat, first upload the FibonacciServlet.class file into your WEB-INF/classes directory. This makes it accessible at a URL based on the class name such as http://www.cafeconleche.org:8080/servlet/FibonacciServlet. Here http://www.cafeconleche.org:8080 is the URL for my servlet context. (Yours will of course be something different.) servlet is the part of the URL that tells the servlet engine it should expect to load a servlet by its class name, and FibonacciServlet is the name of the servlet class.

If you’d like the servlet to be accessible by a more convenient name, edit the web.xml file in the servlet context directory to map the name you want to the name of the class. For example, the following lines map the FibonacciServlet class to the URL http://www.cafeconleche.org:8080/chapter3:

 <servlet>
  <servlet-name>fibonacci</servlet-name>
  <servlet-class>FibonacciServlet</servlet-class>
 </servlet>

 <servlet-mapping>
   <servlet-name>fibonacci</servlet-name>
   <url-pattern>chapter3</url-pattern>
 </servlet-mapping>

In Tomcat 3.2 and earlier, you must shutdown and restart the servlet engine before Tomcat will notice that the web.xml file has changed and use the new mapping.

Note

For more details about servlets, web.xml, Tomcat, and related topics, you might wish to consult the reference I used when writing this chapter, [Inside Servlets, 2nd edition, by Dustin R. Calloway, (Addison Wesley, 2001) ISBN 0-201-70906-6]


Copyright 2001, 2002 Elliotte Rusty Haroldelharo@metalab.unc.eduLast Modified December 14, 2002
Up To Cafe con Leche