Java Servlets – Part 2

Share this article

As we learned in Part 1 of this article, a Java Servlet is a small Java program designed to handle Web browser requests and produce dynamically generated Web pages in response. We have already seen how to write, compile, and deploy simple Servlets. If you aren’t familiar with these tasks, you should read and understand Part 1 before proceeding.

In this second part, we’ll look a little more in depth at what makes Servlets tick. First off, we’ll examine how the HttpServletRequest object can be used to fetch information about the browser request responsible for invoking the Servlet, such as the contents of an HTML form that was submitted as part of the request. Since forms can be submitted both with GET and POST requests, we’ll learn how to make a Servlet that handles these two request types with the same code. We’ll also take another stroll through the web.xml file that I introduced last time to learn how to configure your Servlets on the fly.

Finally, to demonstrate all of these concepts in action, we’ll build a simple Quiz Servlet that you can expand and use to create Web-based multiple choice quizzes.

Handling GET and POST Requests

As I explained in Part 1, a Servlet handles a standard Web page request (using the HTTP GET method) by implementing a method called doGet and using it to produce and send a dynamic response. Now, while the vast majority of page requests on the Web are GET requests, another HTTP request method, POST, is very common as well.

A GET request can submit forms by sending all of the information entered in the form as part of the URL. For example, if a form contained two fields, name and email, and I typed Kevin Yank and kevin@sitepoint.com into the respective fields, then if the form were submitted using HTTP GET the browser would attempt to load a URL such as:

http://www.mysite.com/servlet/Submit?name=Kevin+Yank&email=kevin%40sitepoint.com

The Servlet (Submit in the above example) would then be able to access the values of name and email using the HttpServletRequest object (more on this in the next section).

The POST request method allows forms to be submitted more discretely. Instead of sending the submitted values as part of the URL, the values are sent invisibly as part of the HTTP request body. The mechanics of this are not important; what is important is that this circumvents nasty issues such as submitted passwords (which should presumably remain hidden at all times) appearing in the URL.

In addition, if a user bookmarks the page resulting from a GET submission, the URL that is bookmarked will include all of the information submitted in the form, so that clicking the bookmark will effectively re-submit the form to produce the same page, whereas a bookmark of a POST submission’s results only includes the URL, and none of the submitted form data. There are times when each of these behaviors are desirable (search engines, for instance, tend to use GET so that users can bookmark their favorite searches to quickly resubmit them whenever needed), so you should learn how to handle both of them.

Since handling GET requests with a Servlet requires you to implement a doGet method in your Servlet class, it stands to reason that handling POST requests requires a doPost method. Here’s a simple Servlet that handles both request types (RequestType.java):

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

public class RequestType extends HttpServlet {

 public void doGet(HttpServletRequest req, HttpServletResponse rsp)
               throws ServletException, IOException {
   rsp.setContentType("text/html");
   PrintWriter out = rsp.getWriter();

   out.println("<html>");
   out.println("<head><title> Request Type: GET </title></head>");
   out.println("<body>");
   out.println("<p>This page is the result of a GET request.</p>");
   out.println("</body></html>");
 }

 public void doPost(HttpServletRequest req, HttpServletResponse rsp)
               throws ServletException, IOException {
   rsp.setContentType("text/html");
   PrintWriter out = rsp.getWriter();

   out.println("<html>");
   out.println("<head><title> Request Type: POST </title></head>");
   out.println("<body>");
   out.println("<p>This page is the result of a POST request.</p>");
   out.println("</body></html>");
 }

}

Compile this Servlet (or download RequestType.class) and deploy it on your Tomcat server, then load http://localhost:8080/servlet/RequestType. You should see a page like the following:

Result of a GET RequestIf you have Apache set up with Tomcat, then http://localhost/servlet/RequestType (specifying port 8000 if necessary) should work as well. As you can see, typing a URL to load it in a Web browser produces a GET request, which is handled in this case by our RequestType Servlet’s doGet method. To test out our Servlet’s handling of POST requests, we must create an HTML page with a form in it to submit via POST. Create the following HTML file (PostTest.html):

<html> 
<head>
<title> POST Test </title>
</head>
<body>

 <form method="POST" action="servlet/RequestType">
   <input type="submit" value="POST" />
 </form>

</body>
</html>

As you can see, this page contains a simple HTML form that is set to submit via a POST request (method="POST") to our RequestType Servlet (action="servlet/RequestType"). Place this file in Tomcat’s webappsROOT directory (e.g. D:Program FilesApache Groupjakarta-tomcat-3.2.3webappsROOT) — this is where Tomcat expects to find non-Java Web resources such as HTML and image files. You should then be able to load http://localhost:8080/PostTest.html and click the ‘POST’ button to load the RequestType Servlet with a POST request:

Result of a POST RequestTo try this on your Apache server, you’ll need to place PostTest.html in Apache’s document root directory, or use a JkMount directive in Apache’s configuration file to redirect requests for /PostTest.html to Tomcat as described in Part 1.

Often you’ll want a Servlet to treat GET and POST requests the same way. In most cases you don’t care whether a form is submitted via GET or POST when you’re designing the Servlet to handle its processing, so the fact that you need to implement two different methods to handle both cases may seem like a bit of a pain. Instead, what you can do is write a single doGet method to handle all requests and then just make doPost call the doGet method. Here’s an updated (and somewhat shorter) version of the RequestType Servlet called RequestType2 that does this (RequestType2.java):

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

public class RequestType2 extends HttpServlet {

 public void doGet(HttpServletRequest req, HttpServletResponse rsp)
               throws ServletException, IOException {
   rsp.setContentType("text/html");
   PrintWriter out = rsp.getWriter();

   String requestType = req.getMethod();

   out.println("<html>");
   out.println("<head><title> Request Type: " + requestType +
               " </title></head>");
   out.println("<body>");
   out.println("<p>This page is the result of a " + requestType +
               " request.</p>");
   out.println("</body></html>");
 }

 public void doPost(HttpServletRequest req, HttpServletResponse rsp)
               throws ServletException, IOException {
   doGet(req,rsp);
 }

}

The first thing to notice is that the doPost method has been reduced to a single line, which simply calls the doGet method with the same HttpServletRequest (req) and HttpServletResponse (rsp) parameters:

    doGet(req,rsp);

Now, since this particular Servlet needs to be sensitive to the request type used to invoke it (the whole point of the Servlet is to display the request type), we use the getMethod method of the HttpServletRequest object to get a String (either “GET” or “POST”) to indicate the HTTP method that was used in the request.

    String requestType = req.getMethod();

We then use the requestType variable thus produced in our output lines to display the request type where required. Compile (or download RequestType2.class) and deploy the RequestType2 Servlet and try it out if you like.

Form Handling

As we saw in Part 1, every time a Servlet is asked to handle a page request, it is provided with an HttpServletRequest object, which embodies a complete description of the request. If the page request occurs as a result of a form submission, then this request object contains the values that were submitted in each of the form fields. In this section, I’ll show you how to access those values and use them in your Servlets to produce dynamic pages in response.

Retrieving form parameters in a Servlet is really quite simple; you simply use the getParameter method of the HttpServletRequest object. For example, to retrieve the value of the ‘name’ field and store it in a String variable name, you would use the following:

String name = req.getParameter("name");

Simple, right? Unlike some other languages, Java Servlets use a single method to retrieve request parameters like these whether they were submitted as part of a form with an HTTP POST request, or were included in the URL query string. Let’s see an example of this in practice (Greeting.java):

import java.io.*;  
import javax.servlet.*;  
import javax.servlet.http.*;  
 
public class Greeting extends HttpServlet {  
 
 public void doGet(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   rsp.setContentType("text/html");  
   PrintWriter out = rsp.getWriter();  
 
   // Get the name parameter value  
   String name = req.getParameter("name");  
 
   // If a name was specified, build a personalized greeting  
   String greeting;  
   if (name == null)  
     greeting = "Hi there!";  
   else  
     greeting = "Hi, " + name + "!";  
 
   out.println("<html>");  
   out.println("<head><title> Weclome to my site! </title></head>");  
   out.println("<body>");  
   out.println("<p>" + greeting + "</p>");  
   out.println("</body></html>");  
 }  
 
 public void doPost(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   doGet(req,rsp);  
 }  
 
}

The code given above is relatively straightforward, but let’s break down the important lines:

    // Get the name parameter value  
   String name = req.getParameter("name");

First, we retrieve the ‘name’ parameter. Now, if the request did not include a ‘name’ parameter, this would return null — the Java equivalent of nothing. Thus, before we create a personalized greeting with name, we need to check if it’s null. If it is, we use a more impersonal greeting that doesn’t use name:

    // If a name was specified, build a personalized greeting  
   String greeting;  
   if (name == null)  
     greeting = "Hi there!";  
   else  
     greeting = "Hi, " + name + "!";

Finally, we display greeting as part of the page:

    out.println("<p>" + greeting + "</p>");

Compile this Servlet (or download Greeting.class), then deploy and load it, and you should see something like this:

The generic greetingAs expected, since we didn’t provide a ‘name’ parameter for our request, getParameter("name") returns null, and the generic greeting is displayed. Now, to test the personalized greeting, you could create an HTML file with a form in it like the following:

<form action="/servlet/Greeting" method="POST">  
 Your name: <input type="text" name="name" /><br />  
 <input type="submit" value="Greet me!" />  
</form>

You can do that if you’re especially anxious to see a form submission in action, but for purposes of testing our Servlet we can use a much simpler method. Just add a ‘name’ parameter to the URL you used to load the Servlet above (e.g. http://localhost:8080/servlet/Greeting?name=Kev). This is exactly how the form would be submitted if you specifed method="GET" in the <form> tag above. Here’s what you should see:

The personalized greetingNow, instead of using a separate HTML file with a <form> tag in it, you could have the Servlet itself prompt the user with a form. The following Servlet, Greeting2 (Greeting2.java), is a modified version of the Greeting Servlet we created above. This time, if the ‘name’ parameter is not set, the Servlet displays a form prompting the user for his or her name:

import java.io.*;  
import javax.servlet.*;  
import javax.servlet.http.*;  
 
public class Greeting2 extends HttpServlet {  
 
 public void doGet(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   rsp.setContentType("text/html");  
   PrintWriter out = rsp.getWriter();  
 
   // Get the name parameter value  
   String name = req.getParameter("name");  
 
   // If a name was specified, build a personalized greeting  
   String greeting;  
   if (name == null) {  
     // Get the URL of this Servlet  
     StringBuffer action = HttpUtils.getRequestURL(req);  
 
     greeting =  "<form action="" + action + "" method="POST">n";  
     greeting += "  Your name: ";  
     greeting += "  <input type="text" name="name" /><br />n";  
     greeting += "  <input type="submit" value="Greet me!" />n";  
     greeting += "</form>n";  
   } else greeting = "Hi, " + name + "!";  
 
   out.println("<html>");  
   out.println("<head><title> Weclome to my site! </title></head>");  
   out.println("<body>");  
   out.println("<p>" + greeting + "</p>");  
   out.println("</body></html>");  
 }  
 
 public void doPost(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   doGet(req,rsp);  
 }  
 
}

Let’s look at the important changes here. If the browser doesn’t send a ‘name’ parameter with its request, then the variable name will be assigned a value of null as before. Instead of displaying a generic message, however, our new Servlet will display a form. Since we want that form to be submitted back to the Servlet, we need to obtain the URL that the browser used to load the Servlet and output that as the action parameter of the <form> tag.

One would normally expect the URL to be available from a method of the HttpServletRequest object, but in fact that object only has methods to retrieve small portions of the URL, such as the protocol or path of the request. Instead, the Servlet API includes a class called HttpUtils, which has a number of static methods (methods that belong to the class instead of to objects of the class) for performing useful operations related to Servlets. The HttpUtils.getRequestURL method takes a HttpServletRequest object as a parameter and returns the URL:

    if (name == null) {  
     // Get the URL of this Servlet  
     StringBuffer action = HttpUtils.getRequestURL(req);

The only catch is that it returns the URL as a StringBuffer instead of the more familiar String. StringBuffers are basically just Strings that can be modified without having to create a new object. As far as printing out its value as part of the <form> tag, you can treat it just like a String:

      greeting =  "<form action="" + action + "" method="POST">n";

Note that we place backslashes before any quotes (") in the code so they don’t interfere with the quotes that mark the beginning and end of the String of text. We also use the special n code to represent line breaks that should appear in the HTML.

Compile (or download Greeting2.class) and deploy this new Servlet, then load it (http://localhost:8080/servlet/Greeting2). You should be presented with a form that, when submitted, produces a page with a personalized greeting!

Servlet Initialization Parameters

Like any potentially complex piece of software, Servlets can have configuration settings and options that can be enabled or disabled. In the world of Servlets, these settings are called initialization parameters, and are set in the web.xml file we discussed last time.

A common use of an initialization parameter is to enable debug output. For example, if a Servlet connects to a database to retrieve some information to display on the page, you might want to display the commands that are sent to the database while you are developing the Servlet so that you can be sure everything is working well behind the scenes. But when it comes time to deploy the Servlet in a production environment, you wouldn’t want those debug messages to be displayed. By using an initialization parameter to set whether debug output is displayed, you can easily build a Servlet that is appropriate for use in both development and production environments. Let’s take a look at how this would be done.

The HttpServlet class that all of your Servlets should extend has a getInitParameter method that retrieves the value of an initialization parameter given its name. Since all Servlets are subclasses of HttpServlet, they all inherit that method. Thus, getting the value of an init parameter is as simple as this:

String param = getInitParameter("paramName");

In the case of our parameter for enabling debug output, we could just call getInitParameter("debug") every time we needed to check, but a much more efficient solution (which saves you some typing, too) is to check once when the Servlet is first loaded and store the result as a boolean (true/false) variable.

To perform some action when a Servlet is loaded, you need to give your Servlet an init method. Here’s the skeleton of a Servlet that has a boolean property variable debug that is assigned its value at load time by the init method:

import java.io.*;   
import javax.servlet.*;  
import javax.servlet.http.*;  
 
public class MyDebugServlet extends HttpServlet {  
 
 boolean debug;  
 
 public void init() throws ServletException {  
   String debugParam = getInitParameter("debug");  
   if (debugParam != null &&  
       debugParam.equalsIgnoreCase("true")) {  
     debug = true;  
   } else {  
     debug = false;  
   }  
 }  
 
 // ... doGet, doPost, etc. ...  
}

As you can see, the init method must be declared to throw a ServletException. A ServletException is the type of error that the init method (and most other Servlet methods) can produce to tell the server that something went wrong, and to display an error message because the Servlet isn’t working as expected. I’ll demonstrate this in the final example in this article, but in this case our Servlet won’t have need to produce such errors. Nevertheless, the init method must be declared as if it could.

The first thing init does in the above is to fetch the debug init parameter (getInitParameter("debug")). Like the getParameter function we saw in the previous section (for fetching request parameters), getInitParameter will return null if the parameter was not specified at all. Thus, before we use the debugParam variable, we should make sure it’s not null (trying to call a method on a null variable will cause your Servlet to crash with a NullPointerException error):

if (debugParam != null &&   
   debugParam.equalsIgnoreCase("true")) {

This if statement uses the AND (&&) operator. In words, it says

if debugParam isn’t null and debugParam is “true” (ignoring case)…

Since calling equalsIgnoreCase would cause a NullPointerException if debugParam were null, it’s important that we check that it isn’t first. Java is pretty smart, so if one condition AND (&&) another condition have to be true in an if statement, and it turns out that the first condition is false, then Java won’t bother even checking the second condition. In this case, if debugParam is null then Java will skip the second condition and avoid the crash.

So if the if statement turns out to be true, then we set our debug property variable true. If not, we set debug to false. We can then use this property variable to determine whether or not to display debug output in our doGet method:

if (debug) out.println("Debug output here!");

The following variation on the RequestType2 Servlet we developed at the beginning of this article only displays the request type if the debug parameter is set to true (RequestType3.java):

import java.io.*;   
import javax.servlet.*;  
import javax.servlet.http.*;  
 
public class RequestType3 extends HttpServlet {  
 
 boolean debug;  
 
 public void init() throws ServletException {  
   String debugParam = getInitParameter("debug");  
   if (debugParam != null &&  
       debugParam.equalsIgnoreCase("true")) {  
     debug = true;  
   } else {  
     debug = false;  
   }  
 }  
 
 public void doGet(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   rsp.setContentType("text/html");  
   PrintWriter out = rsp.getWriter();  
 
   String requestType = req.getMethod();  
 
   out.println("<html>");  
   out.println("<head><title> A Web page </title></head>");  
   out.println("<body>");  
 
   if (debug) out.println("<p>This page is the result of a " +  
                          requestType + " request.</p>");  
 
   out.println("<p>Regular page content here...</p>");  
   out.println("</body></html>");  
 }  
 
 public void doPost(HttpServletRequest req, HttpServletResponse rsp)  
               throws ServletException, IOException {  
   doGet(req,rsp);  
 }  
 
}

As you can see, the above code uses the init method from our skeleton code above to set the debug property based on an init parameter, then if debug output is requested we display the request type:

    if (debug) out.println("<p>This page is the result of a " +   
                          requestType + " request.</p>");

Compile (or download RequestType3.class) and deploy this Servlet, then load it. You should only see the “Regular page content here…” paragraph (no debug output):

No debug outputNow, the question remains: how do we set initialization parameters? For this, we return to the web.xml file, which you’ll find in the WEB-INF directory (e.g. C:Program FilesApache Groupjakarta-tomcat-3.2.3webappsROOTWEB-INFweb.xml). You’ll recall in Part 1 we used this file to specify names and mappings for our Servlets. With a new tag, <init-param>, you can set initialization parameters for a Servlet. The following web.xml file, for instance, assigns our RequestType3 Servlet the name rt3 and gives it an initialization parameter called debug with a value of true. The <description> tag is actually optional, but we use it to explain what the parameter does.

<?xml version="1.0" encoding="ISO-8859-1"?>   
 
<!DOCTYPE web-app  
   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"  
   "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">  
 
<web-app>  
 <servlet>  
   <servlet-name>  
     rt3  
   </servlet-name>  
   <servlet-class>  
     RequestType3  
   </servlet-class>  
   <init-param>  
     <param-name>  
       debug  
     </param-name>  
     <param-value>  
       true  
     </param-value>  
     <description>  
       Set to 'true' for debug output.  
     </description>  
   </init-param>  
 </servlet>  
</web-app>

Now if you load the RequestType3 Servlet using its assigned name (http://localhost:8080/servlet/rt3) you’ll see the debug output:

Debug output displayed

A Practical Example: An Online Quiz

A common element on the Web is the multiple-choice question. It can be used in a survey to poll your users for their opinion, or in an educational setting for an online exam; uses for this type of application are many and varied. To solidify the concepts demonstrated in this article, we’ll develop a Servlet that displays a multiple-choice question and then informs the user if their selection was correct. We’ll use our newly-found form handling skills to check their answer, and we’ll use initialization parameters to set the question, the four answers available, and the correct one.

First, let’s start by creating a Servlet that asks a particular question. Once that’s working we’ll adapt it to get the question and answers from initialization parameters. This first version of our quiz Servlet won’t actually be that different from the last example in our section on form handling. Instead of a form prompting for the user’s name, we’ll display the question and four radio buttons for the possible answers. That form, as in the personalized greeting example, will be submitted right back to the same Servlet, which will detect the presence of the request parameter (the selected answer, in this case) and will check if the value corresponds to the correct answer. Here’s the code:

import java.io.*;    
import javax.servlet.*;    
import javax.servlet.http.*;    
   
public class QuizServlet extends HttpServlet {    
   
 public void doGet(HttpServletRequest req, HttpServletResponse rsp)    
               throws ServletException, IOException {    
   rsp.setContentType("text/html");    
   PrintWriter out = rsp.getWriter();    
   
   String answer = req.getParameter("answer");    
   String correct = "C";    
   
   out.println("<html>");    
   out.println("<head><title> Online Quiz </title></head>");    
   out.println("<body>");    
   
   if (answer == null) {    
     StringBuffer action = HttpUtils.getRequestURL(req);    
   
     out.println("<form action="" + action + "" method="POST">n");    
     out.println("<p><b>Question:</b> What is WORA?</p>");    
     out.println("<p><input type="radio" name="answer" " +    
                 "value="A" /> Wear Only Reinforced Acryllic<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="B" /> Where Old Rhinos Assemble<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="C" /> Write Once Run Anywhere<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="D" /> Walk Or Run Anywhere<br />");    
     out.println("   <input type="submit" value="Submit" /></p>");    
     out.println("</form>");    
   } else {    
     if (answer.equals(correct))    
       out.println("<p><b>YES!</b> That's the right answer!</p>");    
     else    
       out.println("<p><b>Sorry.</b> That's the wrong answer.</p>");    
   }    
   
   out.println("</body></html>");    
 }    
   
 public void doPost(HttpServletRequest req, HttpServletResponse rsp)    
               throws ServletException, IOException {    
   doGet(req,rsp);    
 }    
}

Now, this is all well and good, but we want to be able to use this Servlet for more than this single question. To do this, we’ll take the question, answers, and the correct answer out of the code and instead use initialization parameters to set them. The question will come from the question parameter, the answers will be answerA, answerB, answerC, and answerD, while the letter indicating the correct answer will be set by the correct parameter. All of these parameters are read into property variables of the same name in the Servlet’s init method:

  public void init() throws ServletException {    
   question = getInitParameter("question");    
   answerA  = getInitParameter("answerA");    
   answerB  = getInitParameter("answerB");    
   answerC  = getInitParameter("answerC");    
   answerD  = getInitParameter("answerD");    
   correct  = getInitParameter("correct");    
   if (question == null || answerA == null || answerB == null ||    
       answerC == null || answerD == null || correct == null) {    
     throw new ServletException("Missing required init parameter(s)!");    
   }    
 }

At the end of the init method, you’ll notice a rather sizeable if statement. It checks if any of the initialization parameters are missing (and therefore null), using the OR (||) operator to check all the parameters with a single if statement. It can be read aloud “if question is null OR answerA is null OR …”. If any of the required parameters are deemed missing, we throw a ServletException. ServletException is a Java class like any other, so to create an Object of the class we type new followed by the name of the class. ServletException lets us give a reason for the error by passing a string to the constructor, which is exactly what we do above. Finally, the throw keyword indicates that we want to stop execution of the method at that point and pass the error (the ServletException Object) up to whatever code called the method in the first place (in this case, part of the Web server). The Web server would then handle it by displaying an error page in the user’s Web browser in response to any request.

With the parameters loaded, the updated code for producing the form is fairly strightforward:

      out.println("<form action="" + action + "" method="POST">n");    
     out.println("<p><b>Question:</b> " + question + "</p>");    
     out.println("<p><input type="radio" name="answer" " +    
                 "value="A" /> " + answerA + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="B" /> " + answerB + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="C" /> " + answerC + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="D" /> " + answerD + "<br />");    
     out.println("   <input type="submit" value="Submit" /></p>");    
     out.println("</form>");

That’s really all there is to it! Here’s the complete code for our QuizServlet class (QuizServlet.java):

import java.io.*;    
import javax.servlet.*;    
import javax.servlet.http.*;    
   
public class QuizServlet extends HttpServlet {    
   
 String question, answerA, answerB, answerC, answerD, correct;    
   
 public void init() throws ServletException {    
   question = getInitParameter("question");    
   answerA  = getInitParameter("answerA");    
   answerB  = getInitParameter("answerB");    
   answerC  = getInitParameter("answerC");    
   answerD  = getInitParameter("answerD");    
   correct  = getInitParameter("correct");    
   if (question == null || answerA == null || answerB == null ||    
       answerC == null || answerD == null || correct == null) {    
     throw new ServletException("Missing required init parameter(s)!");    
   }    
 }    
   
 public void doGet(HttpServletRequest req, HttpServletResponse rsp)    
               throws ServletException, IOException {    
   rsp.setContentType("text/html");    
   PrintWriter out = rsp.getWriter();    
   
   String answer = req.getParameter("answer");    
   
   out.println("<html>");    
   out.println("<head><title> Online Quiz </title></head>");    
   out.println("<body>");    
   
   if (answer == null) {    
     StringBuffer action = HttpUtils.getRequestURL(req);    
   
     out.println("<form action="" + action + "" method="POST">n");    
     out.println("<p><b>Question:</b> " + question + "</p>");    
     out.println("<p><input type="radio" name="answer" " +    
                 "value="A" /> " + answerA + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="B" /> " + answerB + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="C" /> " + answerC + "<br />");    
     out.println("   <input type="radio" name="answer" " +    
                 "value="D" /> " + answerD + "<br />");    
     out.println("   <input type="submit" value="Submit" /></p>");    
     out.println("</form>");    
   } else {    
     if (answer.equals(correct))    
       out.println("<p><b>YES!</b> That's the right answer!</p>");    
     else    
       out.println("<p><b>Sorry.</b> That's the wrong answer.</p>");    
   }    
   
   out.println("</body></html>");    
 }    
   
 public void doPost(HttpServletRequest req, HttpServletResponse rsp)    
               throws ServletException, IOException {    
   doGet(req,rsp);    
 }    
   
}

If you compile (QuizServlet.class) and deploy this Servlet without specifying any initialization parameters, you’ll see what happens when a Servlet throws a ServletException in its init method:

The result of a ServletExceptionAs you can see, an error page is displayed showing the ServletException, the reason for the error (Missing required init parameter(s)!), and the location in the code where the error occured.

To avoid this unsightly error, let’s add the required parameters to web.xml. Here’s the code you can add for this Servlet (feel free to use your own question and answers):

  <servlet>    
   <servlet-name>    
     quiz    
   </servlet-name>    
   <servlet-class>    
     QuizServlet    
   </servlet-class>    
   <init-param>    
     <param-name>question</param-name>    
     <param-value>What is WORA?</param-value>    
   </init-param>    
   <init-param>    
     <param-name>answerA</param-name>    
     <param-value>Wear Only Reinforced Acryllic</param-value>    
   </init-param>    
   <init-param>    
     <param-name>answerB</param-name>    
     <param-value>Where Old Rhinos Assemble</param-value>    
   </init-param>    
   <init-param>    
     <param-name>answerC</param-name>    
     <param-value>Write Once Run Anywhere</param-value>    
   </init-param>    
   <init-param>    
     <param-name>answerD</param-name>    
     <param-value>Walk Or Run Anywhere</param-value>    
   </init-param>    
   <init-param>    
     <param-name>correct</param-name>    
     <param-value>C</param-value>    
   </init-param>    
 </servlet>

Now load the Servlet again (remember to use the <servlet-name> you assigned in web.xml, or it won’t see the init parameters you just added), and you should see the quiz question appear:

The completed QuizServlet in action

Summary and Further Reading

In the second part of this introductory article on Java Servlets, I introduced some of the more involved concepts of writing Servlets. First, I showed how to handle POST requests with a doPost method, and demonstrated how that method could simply call doGet to have all your request-handling code in one place. Next I showed how the HttpServletRequest object could be used to retrieve request parameters such as the values entered into HTML form fields, or passed as part of the URL query string. The HttpUtils class came in handy when we wanted to create a form that submitted back to the same Servlet that generated it. Finally, I showed how initialization parameters could be used to configure a Servlet when it is deployed. By setting parameters in the web.xml file and checking their values in the init method of the Servlet, we could control how our Servlet behaved without having to change its code and recompile it.

We then took all this knowledge and developed a Web-based quiz Servlet. If you’re looking for some practice, consider how you might expand this Servlet to allow more or less than 4 answers to the question. If you’re really ambitious, consider how you might support a whole quiz with multiple questions, perhaps one per page with a mechanism for tracking the user’s score as he procedes through the quiz!

With the full power of the Java language behind them, Servlets can be very powerful things. What’s more, we’ve only scratched the surface of what the Servlet API has to offer. From session tracking and cookies to password protection and cache control, Servlets are a complete and powerful technology. Their only apparent weakness is the fact that the static HTML portions of a page must be embedded deep in amongst Java code, or stashed as properties in a web.xml file. Either way, it makes life difficult for design staff who are not neccessarily hip to the intricacies of Java Servlets but who want to modify an image or some static text on a page. Technologies such as JavaServer Pages (JSP) seek to remedy this situation by wrapping the Servlet API in a convenient framework that lets you write Java-powered Web pages with Java code appearing in an otherwise normal-looking HTML file. This makes JSP very similar to ASP, PHP, Cold Fusion, and other popular Web Scripting technologies.

Java Servlet Programming 2nd EditionFor a complete and thorough look at the world of Servlets and everything they’re capable of, I recommend Jason Hunter and William Crawford’s excellent book, Java Servlet Programming 2nd Edition. Not only does it cover everything there is to know about Servlets with an incredible level of detail, but it does so while supporting every point with practical examples and lucid, and sometimes humorous discussion. The book also delves into many of the technologies surrounding the Servlets framework, such as JavaServer Pages (JSP).

Frequently Asked Questions about Java Servlets

What is the role of Java Servlets in web development?

Java Servlets play a crucial role in web development as they are used to extend the capabilities of servers that host applications accessed via a request-response model. They are primarily used to handle HTTP requests and responses, making them integral to developing web applications in Java. Servlets are server-side components that provide a powerful mechanism for developing server-side programs.

How do Java Servlets differ from JSP?

While both Java Servlets and Java Server Pages (JSP) are used to create dynamic web content, they have some key differences. Servlets are Java classes that are compiled to bytecode and loaded into the server, while JSPs are text documents that are compiled into Servlets at runtime. Servlets are best for managing complex business logic, while JSP is more suited for presenting dynamic web content and view-related tasks.

How do I create a simple Java Servlet?

Creating a simple Java Servlet involves several steps. First, you need to create a Java class that extends the HttpServlet class. Then, you override the doGet() or doPost() methods to handle GET and POST requests respectively. After that, you need to configure the Servlet in the web.xml file of your web application. Finally, you deploy your web application to a Servlet container like Tomcat to run your Servlet.

What is the Servlet life cycle?

The Servlet life cycle refers to the series of stages a Servlet goes through from creation to destruction. It includes initialization, service, and destruction. In the initialization stage, the Servlet is loaded and initialized. In the service stage, the Servlet handles client requests. In the destruction stage, the Servlet is taken out of service and then garbage collected.

How does a Servlet handle concurrent requests?

A Servlet container can handle multiple requests concurrently. Each request is handled in a separate thread. The Servlet instance variables are shared among all requests, so care must be taken to handle concurrent access to these shared resources.

What is the difference between doGet() and doPost() methods in Servlets?

The doGet() and doPost() methods are used to handle HTTP GET and POST requests respectively. The doGet() method is idempotent, meaning it can be called multiple times without changing the result. It’s used for fetching data. The doPost() method is used for sending data, and calling it multiple times may result in different outcomes.

How can I pass data between Servlets?

Data can be passed between Servlets using request attributes or session attributes. Request attributes are used to pass data from one Servlet to another during a single request. Session attributes are used to pass data between Servlets over multiple requests or a user session.

What is a Servlet filter?

A Servlet filter is an object that can intercept HTTP requests and responses in your web application. You can use Servlet filters to perform a variety of tasks, such as logging, compression, encryption, and authentication.

How do I debug a Servlet?

Debugging a Servlet is similar to debugging any other Java program. You can use a Java IDE like Eclipse or IntelliJ IDEA to set breakpoints and step through your code. You can also use logging frameworks like Log4J to log debug information.

How do I handle exceptions in Servlets?

Exceptions in Servlets can be handled using the standard Java exception handling mechanisms, such as try-catch blocks. You can also use the error-page element in the web.xml file to specify a web page that should be displayed in response to a specific exception or HTTP error code.

Kevin YankKevin Yank
View Author

Kevin Yank is an accomplished web developer, speaker, trainer and author of Build Your Own Database Driven Website Using PHP & MySQL and Co-Author of Simply JavaScript and Everything You Know About CSS is Wrong! Kevin loves to share his wealth of knowledge and it didn't stop at books, he's also the course instructor to 3 online courses in web development. Currently Kevin is the Director of Front End Engineering at Culture Amp.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week