CPSC 220
Fall2004
Servlet Lab

About servlets

As we discussed in class, servlets allow web pages to be generated dynamically. The dynamic content may be based on information stored on the server, e.g., a database, or on information that comes from the client, e.g., information filled into an HTML form. A servlet is just a Java class that implements the javax.servlet.Servlet interface, usually by overriding the HttpServlet class. It then overrides appropriate methods of Servlet to do its work. A servlet essentially produces an entire HTML (or other HTTP) document and sends it to the client. Of course, the web server must know what is going on; it has to recognize a request for a servlet so that it can load the servlet into the servlet engine (which it must be running), execute it, and return its output.

A simple servlet

Consider this simple example servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SimpleServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response) throws ServletException, IOException
  {
    PrintWriter out = response.getWriter();
    out.println("Hello, World");
  }
}
It extends HttpServlet, which just means that it can override some built-in methods that are specific to http. One of these is doGet, which is called in response to a GET request. We'll talk more about the difference between GET and POST requests, but for now just assume that all requests from browsers to web servers are GET requests. Method doGet takes two arguments, an HttpServletRequest (request) and an HttpServletResponse (response). These provide a convenient way for the servlet to get information from and send information to the client (e.g., the browser that made the request). The request argument has methods that let the servlet find out some things about the client (e.g., its IP address, the time of the request, what kind of responses it can handle, and so on, along with any data it chose to send); the response argument has methods that the servlet can use to craft a response. One of these is the getWriter method, which returns a PrintWriter. What the servlet writes to this PrintWriter is sent as its response to the client (after some header information that is set up by the servlet).

Running a servlet

Remember that the web server plays an important role in making servlets work. It has to be able to determine when a request is for a servlet instead of for a static page so that it can execute the servlet program and route the output back to the client. On cs.roanoke.edu, the server expects to find servlets in particular places, and it has been set up so that some of those places are in your home directory. Do the following: To deploy a servlet, you will do the following (don't do these yet -- just read through them):
  1. Put the source code in your webapps/src directory.

  2. Cd to the webapps directory and type ant deploy to the prompt. The ant program is a build tool along the lines of make; it compiles any new (changed since the last compile) files in your src directory and puts the object files in your WEB-INF/classes directory, where the sevlet engine will look for them. Ant is careful; it doesn't replace anything in WEB-INF/classes unless the entire compile succeeds, so you don't get mixed new and old versions there.

  3. Edit web.xml file in the WEB-INF directory to tell Tomcat about your servlet. Open this file and scroll to the bottom. The last two entries should look something like this (java-style comments are not part of the file):
        <servlet>
          <servlet-name>AHello</servlet-name>  //Name this servlet -- may 
                                                     //or may not match class name
          <description>
              Yet another hello world.        //Description -- documentation only
          </description>
          <servlet-class>HelloWorldServlet</servlet-class> //Give name of class
        </servlet>
    
        <servlet-mapping>
          <servlet-name>AHello</servlet-name> //Use servlet name from above
          <url-pattern>/AHello</url-pattern>  //How you want to get this 
                                                    //in a url; note leading /
                                                    //Need not match servlet name
                                                    //but often does
        </servlet-mapping>
    

  4. To view your servlet,go to http://cs.roanoke.edu:8080/username/x, where username is your username and x is the url-pattern above.


Exercise 1 Type in the program above and follow steps 1-4 to save, deploy, and view it. You should get a plaintext version of Hello World in your browser window.

Notice that this servlet returns plain text, not html, and that we didn't include a header in the response. The servlet engine took care of the header for us, just sending its default values for everything; one important line is content-Type, which it sends as text/plain by default. To send a html document, you need to do two things:
  1. Set the content type in the response to be the string "text/html". You can do this in the obvious way with the setContentType method of the response object.
  2. Send the tags required for an html document in addition to its contents. So your first out.println statements should look like this:
    out.println("<HTML>\n");
    out.println("<HEAD><TITLE>Hello</TITLE></HEAD>\n");
    out.println("<BODY>");
    ...
    
    Remember that you should print (to out) exactly what you want in your html document. The \n's aren't really necessary, but they make the HTML a whole lot easier to look at if you ever have to (which you often do for debugging).


Exercise 2: Put this together to write a class HtmlServlet that prints the same thing as SimpleServlet but puts it in an html document. Deploy it as above and confirm that it works.

As you can imagine, generating html like this gets old fast. One easy thing to do is to create a utility class that helps with the boilerplate stuff like the html header. Write such a class (e.g., MyServletUtils) that contains a static method that takes the title of the document as a string and returns a string containing all the html code between <HTML> and </HEAD>. Put this class in your src directory and modify your HtmlServlet class to use it instead of generating all of the html itself.


Often the client sends some information to the servlet that the servlet uses to craft its response -- this might be an order, the answers to a survey, or any other data you can imagine submitting via a web page. This information is often collected with an html form; a simple form that contains a textfield and a submit button is shown below:

Please enter your name:
The text to create this form is as follows (embedded in an HTML file):
<form action="http://cs.roanoke.edu:8080/bloss/MyTest" method="GET">
Please enter your name: 
<input type="text" name="userName"> <br>
<input type="submit" value="Submit">
</form>
When the submit button is pressed, the servlet in MyTest is executed (because it is the form's action -- see the first line) and is passed the information from the form. Since this is part of the request, it shouldn't be surprising that the form information is available to the servlet through its request parameter. Class HttpServletRequest has a getParameter method that takes the name of the parameter and returns its value. For a form, the name of a parameter is usually its name attribute, so for this request the servlet might contain the code
String who = request.getParameter("userName");
If the user typed Mary in the textbox before pressing Submit, string who would then have value Mary. This, of course, can then be used to construct the personalized output.


Exercise 3: Expand your HtmlServlet servlet so that it gets the userName parameter as described above and displays a page that says "Hello, whoever" where whoever is the name that was typed in. To run this servlet you will need to create an html document that contains the form described above (along with a simple header and appropriate BODY tags). Put this document in your public_html directory (which should already exist under your home directory) and load it from the browser (if your username is x, the URL for your public_html directory on cs is http://cs.roanoke.edu/~x). You should see your simple form; type in your name and press the Submit button, and you should get a personalized greeting!

When you press Submit in the program above, you will notice that the name parameter had been attached to the URL as ?name=Mary. This is how parameter information is sent in a GET request, and you can do this explicitly as well. Instead of loading your test html page, just type in http://cs.roanoke.edu:8080/x/y?name=Mary (where x is your user id and y is the url-name for your servlet). You will get the same thing you got before -- the servlet can't tell how the input was generated, it just reads what comes after the ?.


Exercise 4: You can use this to do fun things with a servlet. Write a servlet that creates an infinite document in which each page does the following:

For example, page 2 of this document might look like this:

Page 2

Previous Page Next Page

When you click on Next Page, you should get page 3, which looks similar (except with a 3, of course). When you click on Previous Page, you should get page 1.

Notice that Previous Page and Next Page are links, so you would create them with the (anchor) tag (just think carefully about where you want to link to!). If you don't know enough html to do this, consult one of the many html tutorials on the web -- my favorite for basics is at http://www.cwru.edu/help/introHTML/toc.html.

When your infinite document works, think about this: what should happen when you click on Previous Page from page 1? Fix it so that it does something nicer than run through an infinite number of negative pages.