Guide to Java Servlets

Servlets are Java classes that conform to the Java Servlet API, which allows a Java class to respond to requests. Although servlets can respond to any type of request, they are most commonly written to respond to web-based requests. A servlet must be deployed to a Java servlet container in order to become usable.

Although many developers use servlet frameworks such as Java Server Pages (JSP) and Java Server Faces (JSF), both of those technologies compile pages into Java servlets behind the scenes via the servlet container. That said, a fundamental knowledge of Java servlet technology could be very useful for any Java web developer.

In this tutorial, we will cover the below topics to get an overall understanding of java servlet technology.

1. The First Servlet

Our first servlet is a very simple servlet having very minimum code so that you can only focus on what matters.

package com.howtodoinjava.servlets;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class MyFirstServlet extends HttpServlet {
 
  private static final long serialVersionUID = -1915463532411657451L;
 
  @Override
  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException 
  {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {
      // Write some content
      out.println("<html>");
      out.println("<head>");
      out.println("<title>MyFirstServlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h2>Servlet MyFirstServlet at " + request.getContextPath() + "</h2>");
      out.println("</body>");
      out.println("</html>");
    } finally {
      out.close();
    }
  }
   
  @Override
  protected void doPost(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    //Do some other work
  }
 
  @Override
  public String getServletInfo() {
    return "MyFirstServlet";
  }
}

To register the above servlet with the web container, we will make an entry web.xml file.

<?xml version="1.0"?>
<web-app   xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
      http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">
       
...
   
  <servlet>
    <servlet-name>MyFirstServlet</servlet-name>
    <servlet-class>com.howtodoinjava.servlets.MyFirstServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyFirstServlet</servlet-name>
    <url-pattern>/MyFirstServlet</url-pattern>
  </servlet-mapping>

...
   
</web-app>

The above servlet does a few important things, we may want to learn.

  • MyFirstServlet extends HttpServlet. This is mandatory because all servlets must be either a generic servlet that extends javax.servlet.GenericServlet or an HTTP servlet that extends javax.servlet.http.HttpServlet.
  • Overriding doGet() and doPost() methods. These methods are defined in HttpServlet class. Whenever a GET or POST request come, it is mapped to it’s respective method e.g. if you send a
  • HTTP GET request to this servlet, then doGet() method is called.
    There are some other useful methods as well which you can override to control the application in runtime e.g. getServletInfo().
  • HttpServletRequest and HttpServletResponse are default parameters to all doXXX() methods. We will learn more about these objects in later section.

2. Servlet Life Cycle

Whenever in our application, a servlet is loaded and used; there occur a series of events during the initialization and destruction of that servlet. These are called life cycle events (or methods) of servlet.

Three methods are central to the life cycle of a servlet. These are init(), service(), and destroy(). They are implemented by every servlet and are invoked at specific times by the runtime.

init(): During the initialization stage of the servlet life cycle, the web container initializes the servlet instance by calling the init() method, and passing an object implementing the javax.servlet.ServletConfig interface. This configuration object allows the servlet to access name-value initialization parameters defined in web.xml file of the web application. This is called only once in the lifetime of that servlet instance.

The init method definition looks like this:

public void  init() throws ServletException {
	//custom initialization code
}

service(): After initialization, the servlet instance can service client requests. The web container calls the service() method of the servlet for every request. The service() method determines the kind of request being made and dispatches it to an appropriate method to handle the request. The developer of the servlet must provide an implementation for these methods.

If a request is made for a method that is not implemented by the servlet, the method of the parent class is called, typically resulting in an error being returned to the requester.

There’s no need to override this method in ‘almost’ all situations.

protected void service(HttpServletRequest req, HttpServletResponse resp)  throws ServletException, IOException { 

    ... 
}

destroy(): Finally, the web container calls the destroy() method that takes the servlet out of service. We should call this method if you want to close or destroy some filesystem or network resources before the servlet goes out of scope. The destroy() method, like init(), is called only once in the lifecycle of a servlet.

public void destroy() {
	//
}

Usually, you do not need to override any of them in your servlet in most of the scenarios.

Read More : How web servers work?

3. @WebServlet Annotation

If you are not very fond of XML configurations, and rather like annotations particularly then Servlets API has something for you need as well. You can use @WebServlet annotation as the below example and then you do not need to make any entry in web.xml. Container will automatically register your servlet into runtime, and process it as usual.

import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@WebServlet(name = "MyFirstServlet", urlPatterns = {"/MyFirstServlet"})
public class MyFirstServlet extends HttpServlet {
 
  private static final long serialVersionUID = -1915463532411657451L;
 
  @Override
  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException 
  {
    //Do some work
  }
   
  @Override
  protected void doPost(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    //Do some other work
  }
}

4. Packaging and Deploying Servlet into Tomcat Server

If we are using any IDE (e.g. eclipse) then packaging and deploying our application is simply one step. Right click on project > Run As > Run As Server. Configure the server if not done already and we are ready to roll.

If we are not using any IDE, then we need to do some additional work e.g compiling the application from the command prompt, using ANT to create a war file etc. But I am pretty confident that everyone nowadays uses some IDE for development, so I will not waste more time in this section.

When you deploy our first servlet in tomcat and hit the URL “http://localhost:8080/servletexamples/MyFirstServlet” in browser, you will get below response.

servlet example

5. Writing to a Servlet Response

One of the reasons why Java servlets are so useful is because they allow dynamic content to be displayed on a web page. The content can be taken from the server itself, a database, another website, or any other web-accessible resources. Servlets are not static web pages; they are dynamic, and that is arguably their biggest strength.

Let’s take the example of a servlet that is responsible for displaying the current date and time to the user, along with his name and some custom message.

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@WebServlet(name = "CalendarServlet", urlPatterns = {"/CalendarServlet"})
public class CalendarServlet extends HttpServlet {
 
  private static final long serialVersionUID = -1915463532411657451L;
 
  @Override
  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException 
  {
     
    Map<String,String> data = getData();
     
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {
      // Write some content
      out.println("<html>");
      out.println("<head>");
      out.println("<title>CalendarServlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h2>Hello " + data.get("username") + ", " + data.get("message") + "</h2>");
      out.println("<h2>The time right now is : " + new Date() + "</h2>");
      out.println("</body>");
      out.println("</html>");
    } finally {
      out.close();
    }
  }
   
  //This method will access some external system as database to get user name, and his personalized message
  private Map<String, String> getData() 
  {
    Map<String, String> data = new HashMap<String, String>();
    data.put("username", "Guest");
    data.put("message",  "Welcome to my world !!");
    return data;
  }
}

When you run the above servlet in tomcat and hit the URL “http://localhost:8080/servletexamples/CalendarServlet” in a browser, you will get the below response.

dynamic content in servlet

6. Handling Servlet Requests and Responses

Servlets make it easy to create web applications that adhere to a request and response life cycle. They have the ability to provide HTTP responses and also process business logic within the same body of code. The ability to process business logic makes servlets much more powerful than standard HTML code.

In real-world applications, an HTML web form contains parameters that are sent to a servlet. The servlet then processes those parameters in some fashion and publishes a response that can be seen by the client. In the case of an HttpServlet object, the client is a web browser, and the response is a web page. The <form> action attribute states that it should be used to process the values that are contained within the form.

To obtain request parameters, call the HttpServletRequest object’s getParameter() method, passing the id of the input parameter you want to obtain.

String value1 = httpServletRequest.getParameter("param1");
String value1 = httpServletRequest.getParameter("param2");

Once the values are obtained, they can be processed as needed. Then the response for the client is prepared as we discussed in the above sections. This response is sent back to the client using HttpServletResponse object.

A basic usage of request and response processing can be done like this:

@Override
protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   
  response.setContentType("text/html;charset=UTF-8");
  PrintWriter out = response.getWriter();
   
  String username = request.getParameter("username");
  String password = request.getParameter("password");
   
  boolean success = validateUser(username, password);
   
  try {
    // Write some content
    out.println("<html>");
    out.println("<head>");
    out.println("<title>LoginServlet</title>");
    out.println("</head>");
    out.println("<body>");
 
    if(success) {
      out.println("<h2>Welcome Friend</h2>");
    }else{
      out.println("<h2>Validate your self again.</h2>");
    }
     
    out.println("</body>");
    out.println("</html>");
  } finally {
    out.close();
  }
}

For sending the content, you will have to use PrintWriter object obtained from HttpServletResponse. Any content written to it will be written into outputstream and data will be sent back to client.

7. Listening for Servlet Container Events

Sometimes it is useful to know when certain events occur within the application server container. This concept can be useful under many different circumstances, but most often it would likely be used for initializing an application upon start-up or cleaning up after an application upon shutdown. A servlet listener can be registered with an application to indicate when it has been started up or shut down. Therefore, by listening for such events, the servlet has the opportunity to perform some actions when they occur.

To create a listener that performs actions based upon a container event, you must develop a class that implements the ServletContextListener interface. The methods that need to be implemented are contextInitialized() and contextDestroyed(). Both of the methods accept a ServletContextEvent as an argument, and they are automatically called each time the servlet container is initialized or shut down, respectively.

To register the listener with the container, you can use one of the following techniques:

1) Utilize the @WebListener annotation.
2) Register the listener within the web.xml application deployment descriptor.
3) Use the addListener() methods defined on ServletContext.

Please note that ServletContextListener is not the only listner in servlet API. There are some more e.g.

  • javax.servlet.ServletRequestListener
  • javax.servlet.ServletRequestAttrbiteListener
  • javax.servlet.ServletContextListener
  • javax.servlet.ServletContextAttributeListener
  • javax.servlet.HttpSessionListener
  • javax.servlet.HttpSessionAttributeListener

They can be implemented by your listner class based on choice that which all events you want to listen to; e.g. HttpSessionListener will be notified everytime a new user session is created or destroyed.

8. Passing Parameters to Servlet Initialization

Most of today’s application needs to set some configuration parameters which you can pass them upon application/controller startup. Servlets also can receive initialization parameters which they can use to fully construct them before serving their first request.

Obviously, you can hard-code the configuration values in servlet itself, but changing any of them will require you to recompile whole application again, and nobody would love to do that.

<web-app>
    <servlet>
        <servlet-name>SimpleServlet</servlet-name>
        <servlet-class>com.howtodoinjava.servlets.SimpleServlet</servlet-class>
     
    <!-- Servlet init param -->
        <init-param>
            <param-name>name</param-name>
            <param-value>value</param-value>
        </init-param>
 
    </servlet>
 
</web-app>

Once set, the parameter can be used within code by calling getServletConfig().getInitializationParameter() and passing the name of the parameter, as shown in the following line of code:

String value = getServletConfig().getInitParameter("name");

9. Servlet Filters

Web filters are useful for pre-processing requests and invoking certain functionality when a given URL is visited. Rather than invoking a servlet that exists at a given URL directly, any filter that contains the same URL pattern will be invoked prior to the servlet. This can be helpful in many situations, perhaps the most useful for performing logging, authentication, or other services that occur in the background without user interaction.

Filters must implement the javax.servlet.Filter interface. Methods contained within this interface include init(), destroy(), and doFilter(). The init() and destroy() methods are invoked by the container. The doFilter() method is used to implement tasks for the filter class. If you want to chain filters or if more than one filter exists for a given URL pattern, they will be invoked in the order in which they are configured in the web.xml deployment descriptor.

To configure the web.xml file to include a filter, use the <filter> and <filter-mapping> XML elements along with their associated child element tags.

<filter>
    <filter-name>LoggingFilter</filter-name>
    <filter-class>LoggingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LogingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

If you want to use annotation to configure filters for specific servlets, you can use @WebFilter annotation.

10. Downloading a Binary File using Servlet

Downloading files is an essential task for almost any web application. To download a file, the servlet must provide a response of the same type that matches that of the file to be downloaded. It must also indicate in the response header that an attachment is to be included like below.

String mimeType = context.getMimeType( fileToDownload );
response.setContentType( mimeType != null ? mimeType : "text/plain" );
response.setHeader( "Content-Disposition", "attachment; filename=\"" + fileToDownload + "\"" );

You can obtain a reference to the file that is to be downloaded (stored in filesystem) by calling the ServletContext.getResourceAsStream() method and passing the path of the file. This will return an InputStream object that can be used to read the contents of the file. A byte buffer is then created, which will be used to obtain chunks of data from the file when it is being read.

The final real task is to read the file contents and copy them to the output stream. This is done using a while loop, which will continue to read from the InputStream until everything has been processed. Chunks of data are read in and written to the output stream using the loop. After this, ServletOutputStream object’s flush method is called to clear the contents and release the resources.

Let’s look at sample code

private void downloadFile(HttpServletRequest request, HttpServletResponse response, String fileToDownload) throws IOException
  {
    final int BYTES = 1024;
    int length = 0;
     
    ServletOutputStream outStream = response.getOutputStream();
    ServletContext context = getServletConfig().getServletContext();
 
    String mimeType = context.getMimeType( fileToDownload );
    response.setContentType( mimeType != null ? mimeType : "text/plain" );
    response.setHeader( "Content-Disposition", "attachment; filename=\"" + fileToDownload + "\"" );
 
    InputStream in = context.getResourceAsStream("/" + fileToDownload);
     
    byte[] bbuf = new byte[BYTES];
 
    while ((in != null) && ((length = in.read(bbuf)) != -1)) {
      outStream.write(bbuf, 0, length);
    }
 
    outStream.flush();
    outStream.close();
  }

11. Forward Request to Another Servlet

Sometimes, your application require that a servlet should hands off requests to other servlets to complete the task that needs to be accomplished. Furthermore, the requests should be handed off without redirecting the client to another URL i.e. the URL in the browser should not change.

The facilities for doing so are built right into the ServletContext, so once you obtain a reference to ServletContext, then you simply call the getRequestDispatcher() method to obtain a RequestDispatcher object that can be used to dispatch the request.

When calling the getRequestDispatcher() method, pass a String containing the name of the servlet that you want to hand off the request to. After a RequestDispatcher object has been obtained, invoke its forward method by passing the HttpServletRequest and HttpServletResponse objects to it. The forward method performs the task of handing off the request.

RequestDispatcher rd = servletContext.getRequestDispatcher("/NextServlet");
rd.forward(request, response);

12. Redirect Request to Another Servlet

Though is some scenarios you will not like to notify user that servlet redirection has happened as we saw in previous section, but in some scenarios we actually want that to happen. You want to redirect the browser to another URL when a specific URL within your application is visited.

To do this, you will need to call sendRedirect() method of HttpServletResponse object.

httpServletResponse.sendRedirect("/anotherURL");

This simple redirect, as opposed to servlet chaining, does not pass the HttpRequest object along to the target address.

13. Read/Write Cookies using Servlets

Many applications wants to store user’s current state of user browsing history in clients machine so that when user return to application again, he start from where he left. Usually for this requirement, cookies are used. You can see cookies as key-value pair based data stored on client’s machine. When application is accesses in browser then application is able to read or write these values.

To create a cookie, simply instantiate a new javax.servlet.http.Cookie object and assign a name and value to it. Once the cookie has been instantiated, properties can be set that will help to configure the cookie. In the example to this recipe, the cookie’s setMaxAge() and setHttpOnly() methods are called, setting the time of life for the cookie and ensuring that it will be guarded against client-side scripting.

Since Servlet 3.0 API, the ability to mark a cookie as HTTP only has become available. This allows the cookie to be safeguarded against client-side scripting attacks, making the cookie more secure.

Cookie cookie = new Cookie("sessionId","123456789");
cookie.setHttpOnly(true);
cookie.setMaxAge(-30);
response.addCookie(cookie);

Here response is instance of HttpServletResponse passed to doXXX() method.

To read back the cookie information on server sire, use following code:

Cookie[] cookies = request.getCookies();

for(Cookie cookie : cookies) {
	//cookie.getName();
	//cookie.getValue()
}

That’s all for this tutorial about servlets technology. Feel free to drop comment/feedback.

Happy Learning !!

Comments

Subscribe
Notify of
guest
6 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.