Complete Java Servlets Tutorial

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 below topics to get overall understanding of java servlet technology.

Table of Contents

Writing your first Servlet
Servlet Life Cycle Methods
Develop Servlet with @WebServlet Annotation
Packaging and Deploying Servlet into Tomcat Server
Writing dynamic content in Servlet response
Handling Servlet Request and Response
Listening for Servlet Container Events
Passing Servlet Initialization Parameters
Adding Servlet Filters for Specific URL Requests
Downloading a binary file using Servlet
Forward request to another servlet using RequestDispatcher.forward()
Redirect request to another servlet using HttpServletResponse.sendRedirect()
Writing and Reading Cookie using Servlets

Let’s start learning about servlets step by step.

Writing your first Servlet

Our first servlet is 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 above servlet with web container, you will make an entry web.xml file for your application.

<?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">
			
	<welcome-file-list>
		<welcome-file>/MyFirstServlet</welcome-file>
	</welcome-file-list>
	
	<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>

Above servlet does few important things, you may want to learn.

  1. 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.
  2. 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
  3. 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().
  4. HttpServletRequest and HttpServletResponse are default parameters to all doXXX() methods. We will learn more about these objects in later section.

That’s pretty all about a simple servlet you should know.

Servlet Life Cycle Methods

Whenever in your 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. Let’s read more about them.

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.

1) During initialization stage of the servlet life cycle, the web container initializes the servlet instance by calling the init() method, 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 lifetime of that servlet instance.

The init method definition looks like this:

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

2) 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
{
String method = req.getMethod();

if (method.equals(METHOD_GET)) {
	long lastModified = getLastModified(req);
	if (lastModified == -1) {
	// servlet doesn't support if-modified-since, no reason
	// to go through further expensive logic
	doGet(req, resp);
	} else {
	long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
	if (ifModifiedSince < (lastModified / 1000 * 1000)) {
		// If the servlet mod time is later, call doGet()
				// Round down to the nearest second for a proper compare
				// A ifModifiedSince of -1 will always be less
		maybeSetLastModified(resp, lastModified);
		doGet(req, resp);
	} else {
		resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
	}
	}

} else if (method.equals(METHOD_HEAD)) {
	long lastModified = getLastModified(req);
	maybeSetLastModified(resp, lastModified);
	doHead(req, resp);

} else if (method.equals(METHOD_POST)) {
	doPost(req, resp);
	
} else if (method.equals(METHOD_PUT)) {
	doPut(req, resp);	
	
} else if (method.equals(METHOD_DELETE)) {
	doDelete(req, resp);
	
} else if (method.equals(METHOD_OPTIONS)) {
	doOptions(req,resp);
	
} else if (method.equals(METHOD_TRACE)) {
	doTrace(req,resp);
	
} else {
	//
	// Note that this means NO servlet supports whatever
	// method was requested, anywhere on this server.
	//

	String errMsg = lStrings.getString("http.method_not_implemented");
	Object[] errArgs = new Object[1];
	errArgs[0] = method;
	errMsg = MessageFormat.format(errMsg, errArgs);
	
	resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}

3) Finally, the web container calls the destroy() method that takes the servlet out of service. You 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?

Develop Servlet with @WebServlet Annotation

If you are not very fond of xml configurations, and rather like annotations particularly then Servlets API has something you as well. You can use @WebServlet annotation as 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.

package com.howtodoinjava.servlets;

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
	}
}

Packaging and Deploying Servlet into Tomcat Server

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

If you are not using any IDE, then you need to do some additional work e.g compiling the application from 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

Writing dynamic content in 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 web site, or many other web-accessible resources. Servlets are not static web pages; they are dynamic, and that is arguably their biggest strength.

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

package com.howtodoinjava.servlets;

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 above servlet in tomcat and hit the URL “http://localhost:8080/servletexamples/CalendarServlet” in browser, you will get below response.

dynamic content in servlet

Handling Servlet Request and Response

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 which 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 = req.getParameter("param1");
String value1 = req.getParameter("param2");

Once the values are obtained, they can be processed as needed. Then the response for client is prepared as we discussed in above sections. This response is sent back to 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.

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.

Passing Servlet Initialization Parameters

Most of the 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");

Adding Servlet Filters for Specific URL Requests

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.

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();
	}

Forward request to another servlet using RequestDispatcher.forward()

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);

Redirect request to another servlet using HttpServletResponse.sendRedirect()

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.

Writing and Reading Cookie 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 !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

6 thoughts on “Complete Java Servlets Tutorial”

  1. if we want to send some proper message say “server not yet ready….” when init method is not yet completed but client hits any request.how to handle this situation?

  2. Thanks a lot for the article. I just needed some information about servlets and suddenly i received an information email about this article 🙂 It was my lifebuoy.

Comments are closed.

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.