Request handling is the bread and butter of Java web application development. In order to respond to requests from the network, a Java web application must first determine what code will respond to the request URL, then marshal a response. Every technology stack has a way of accomplishing request-response handling. In Java, we use servlets (and the Java Servlet API) for this purpose. Think of a servlet as a tiny server whose job is to accept requests and issue responses.
Software as layers
As I explained in my introduction to the Java Runtime Environment, we can view software as a series of layers. Each layer in a software system holds certain capabilities that are required by the layers above it. As an example, the hardware layer sits below the firmware layer, supporting its functionality. Likewise, the firmware layer (BIOS on a PC or EFI on a Mac) is needed to run the operating system. Figure 1 shows these three components in a layered diagram.
You could also look at a software system as a series of containers, where the lower layers act as containers for the higher ones. Each layer acts as a context for running the next level of functionality: hardware contains firmware, and firmware contains the operating system.
A server-side Java application is one of a broad class of applications that serve as network endpoints, receiving HTTP requests from a given URL and sending back data in an interchange format like HMTL or JSON. Server-side Java consists of both standardized Java servers and technologies for interacting with those servers. The Java Servlet API is the standard used to interact with a Java server.
Java servers and the JVM
In Java-based systems, the operating system (OS) contains the JVM, which provides a consistent environment for running Java applications. A Java server sits on top of the JVM. Just as the JVM is the intermediary between the OS and your Java application, the Java server provides consistent, streamlined access to the operating system’s networking and processing capabilities. A Java application runs inside the server, using the Java Servlet API to access the server’s capabilities.
Figure 2 shows a software stack for server-side Java.
The Java Servlet specification
The Java Servlet specification provides the underlying definition for a Java server and related components. It defines how the server will send requests and responses during network interactions over HTTP. All Java servers must be compatible with the Java Servlet specification. Most Java servers today are compatible with Servlet 4.0.
For a practical understanding of how the Servlet specification works, consider the article you are currently reading. Somewhere in the bowels of JavaWorld’s infrastructure, this article was formatted and submitted for publication. It was assigned a URL, routed through the network, and arrived at a server. The server connected the artifact (article) with the URL and determined that when a GET request arrived for that URL, it would serve back this article as HTML.
When you create a Java web application, you are creating software that runs inside the Java server. The application utilizes the facilities provided by the server context, and one of those facilities is the Servlet API. For this reason, a Java server that implements the Servlet specification is sometimes called a servlet container.
To create a servlet, you implement the
Servlet interface and deploy it inside a servlet container. Figure 3 shows how your application relies on the servlet.
Writing servlets with Tomcat
Now that you’ve got a conceptual overview, let’s get down to the business of writing a Java servlet.
The first thing you’ll need is a servlet container, otherwise known as a Java application server. Tomcat and Jetty are two of the most popular servlet containers. We’ll use Tomcat because it’s one of the most long-standing application servers for Java. Tomcat is free and contains minimal bells and whistles, which will keep things simple for our example. (“Bells and whistles” is a technical term, by the way.)
Download and install Tomcat
If you don’t already have Tomcat, start by opening the Tomcat download page. There, you can select either the Windows installer or the most appropriate ZIP download for your computer (for example, I’m downloading the 64-bit Windows zip).
That’s it: you’ve just added the Java server layer to your operating system!
Verify Tomcat is running
Before going further, let’s make sure you can run Tomcat. Either start the Windows service or run
startup.bat file from the command-line.
If you now open a web browser and go to
localhost:8080, you should be greeted by the following screen:
If you encounter any problems running Tomcat, you can visit the Tomcat documentation for troubleshooting.
Run the Tomcat servlet example
Now let’s get a look at a Java servlet. Conveniently, Tomcat has included some simple examples.
Click on the Examples link you see in the Developer Quick Start section of the Tomcat welcome page. Once you’re there, click the Servlet Examples link.
Now you can see a simple Servlet in action by clicking the
Hello World sample’s
Execute link. That will bring your browser to the http://localhost:8080/examples/servlets/servlet/HelloWorldExample URL, where you will see the perennial programmer’s salutation.
Viewing the servlet source code
Click the Back arrow in your browser, then click the source link for the HelloWorld app. The source is shown in Listing 1.
Listing 1. Source code for HelloWorld example
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Hello World!</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello World!</h1>"); out.println("</body>"); out.println("</html>");
This very simple code listing contains the basic components of a Java servlet. Let’s consider it step by step.
The first line calls the standard Java imports. After that, the program defines a new class, which extends the
HttpServlet class. This is critical because servlets must implement the
Servlet interface in order to run inside a servlet container.
HelloWorld class defines a method called
doGet(). This is a standard method on servlets: it tells the server to route
HTTP GET requests to this method. Other HTTP methods, like POST, are handled by similarly named methods, like
Notice that that
doGet() has two parameters:
(HttpServletRequest request, HttpServletResponse response). These two objects represent the request and response. They provide access to everything your code needs to deal with the request and issue a response. In the
HelloWorld.doGet servlet method, for example, the
response object is used to inform the server what content type header to issue. In this case, it’s
Finally, the program obtains a Java Writer object from the response
Writer is then used to create a simple HTML response to return to the browser.
The structure and code flow in Listing 1 are fairly intuitive, but there is a glaring omission. How does the server know to associate the
http://localhost:8080/examples/servlets/servlet/HelloWorldExample URL to the
You will find the answer to this mystery in the application meta-data. Every Java web application includes a standard meta-data file, called
web.xml, which tells the server how to map URLs to servlets.
In the Tomcat example apps, the
web.xml is found at
WEB-INFweb.xml is the standard location of the meta-data file for servlets. If you open this file, you’ll see how the server is configured.
web.xml in Listing 2 has just the information we need for our discussion.
Listing 2. Source code for the Tomcat HelloWorld example
<?xml version="1.0" encoding="UTF-8"?> <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://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <!-- ...CODE REMOVED FOR BREVITY... --> <servlet> <servlet-name>HelloWorldExample</servlet-name> <servlet-class>HelloWorldExample</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorldExample</servlet-name> <url-pattern>/servlets/servlet/HelloWorldExample</url-pattern> </servlet-mapping> <!-- ...CODE REMOVED FOR BREVITY... --> </web-app>
Listing 2 shows a typical XML file header referencing the schema for a Java web application descriptor. This is followed by two entries:
The call to
<servlet> assigns a logical name,
HelloWorldExample, to the
HelloWorldExample class, via the <servlet-name> and <servlet-class> fields.
The call to
<servlet-mapping> assigns that logical name to the
<url-pattern> value, thereby associating the code to the URL.
Note that the
<url-pattern> field supports wild cards in order to handle a variety of flexible URL mappings.
Other servlet capabilities
In addition to URL mapping, servlets provide additional capabilities for filtering and authentication. Filters are used for processing requests, and authentication is used to assign simple users and roles to URL patterns. The JavaServer Pages (JSP) specification provides support for generating HTML in a much more powerful way.
This article has been a conceptual overview of Java servlets, including URL request and response handling inside a Java server. Understanding these basic elements of server-side Java will help you integrate more advanced concepts such as server push and runtime discovery of URL mappings, which are new in Servlet 4.0.
This story, “What is a Java servlet? Request handling for Java web applications” was originally published by
Share this post if you enjoyed! 🙂