Questions tagged [servlets]

Servlet is a Java application programming interface (API) running on the server machine which can intercept the requests made by the client and can generate/send a response accordingly.

Servlets

A Servlet is a Java application programming interface (API) running on the server machine which can intercept requests made by the client and can generate/send a response accordingly. A well-known example is the HttpServlet which provides methods to hook on HTTP requests using the popular HTTP methods such as GET and POST. You can configure HttpServlets to listen on a certain HTTP URL pattern, which is configurable in web.xml, or more recently with Java EE 6, with @WebServlet annotation. Many Java EE web frameworks are built on top of servlets, such as JSF, JAX-RS, Spring MVC, Struts, Wicket, etcetera. See also What is the difference between JSF, Servlet and JSP?

Lifecycle

When a Servlet is requested for the first time or when the web app starts up, the servlet container will create an instance of it and keep it in memory during the web app's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the requested data by HttpServletRequest and handle the response by HttpServletResponse. Both objects are available as method arguments inside of any of the overridden methods of HttpServlet, such as doGet() to preprocess a request and doPost() to post-process a request. See also How do servlets work? Instantiation, sessions, shared variables and multithreading.

Installation

In order to run Servlets, you need:

  • JDK (JRE is only sufficient if the server has its own compiler).
  • A servlet container.
  • Optionally, a Java EE aware IDE (Integrated Development Editor).

There are several servlet containers.

There are also Java EE application servers which in turn also contain a servlet container besides other Java EE APIs such as JSF, JPA, EJB, etc. See also What exactly is Java EE?

Installing a servlet container is generally just a matter of downloading the zip/gz file and extracting it at the location of your choice.

Generally, you'd also like to use an IDE such as Eclipse, IntelliJ or Netbeans so you don't need to manually compile and build the source files with javac over and over. Decent IDEs have plugins to seamlessly integrate the servlet container and import the necessary Java EE APIs into the build path of the project. See also How do I import the javax.servlet API in my Eclipse project?

Hello World #1 (post-process a request)

Post-processing a request such as submitting and validating a POST form is the most commonly known use case for a servlet. The action attribute of an HTML <form> can point to a servlet URL and the method="post" would trigger the servlet's doPost() method where you have all the freedom to control the HTTP request and response.

Assuming that there's a JSP in /WEB-INF/hello.jsp which looks like this...

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Servlet Hello World</title>
        <style>.error { color: red; } .success { color: green; }</style>
    </head>
    <body>
        <form action="hello" method="post">
            <h1>Hello</h1>
            <p>
                <label for="name">What's your name?</label>
                <input id="name" name="name" value="${fn:escapeXml(param.name)}">
                <span class="error">${messages.name}</span>
            </p>
            <p>
                <label for="age">What's your age?</label>
                <input id="age" name="age" value="${fn:escapeXml(param.age)}">
                <span class="error">${messages.age}</span>
            </p>
            <p>
                <input type="submit">
                <span class="success">${messages.success}</span>
            </p>
        </form>
    </body>
</html>

(the fn:escapeXml() is to protect your page against XSS while redisplaying user-controlled input; if JSTL doesn't work in general, then probably your servlet container doesn't support it out of the box (like Tomcat); you can install it by just dropping jstl-1.2.jar in /WEB-INF/lib, see also JSTL info page)

...here's how the com.example.controller.HelloServlet class should look:

package com.example.controller;

import java.io.IOException;
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("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Preprocess request: we actually don't need to do any business stuff, so just display JSP.
        request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Postprocess request: gather and validate submitted data and display the result in the same JSP.

        // Prepare messages.
        Map<String, String> messages = new HashMap<String, String>();
        request.setAttribute("messages", messages);

        // Get and validate name.
        String name = request.getParameter("name");
        if (name == null || name.trim().isEmpty()) {
            messages.put("name", "Please enter name");
        } else if (!name.matches("\\p{Alnum}+")) {
            messages.put("name", "Please enter alphanumeric characters only");
        }

        // Get and validate age.
        String age = request.getParameter("age");
        if (age == null || age.trim().isEmpty()) {
            messages.put("age", "Please enter age");
        } else if (!age.matches("\\d+")) {
            messages.put("age", "Please enter digits only");
        }

        // No validation errors? Do the business job!
        if (messages.isEmpty()) {
            messages.put("success", String.format("Hello, your name is %s and your age is %s!", name, age));
        }

        request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
    }
    
}

Compile the code and put it in the /WEB-INF/classes folder. In this particular case, the class file should end up in /WEB-INF/classes/com/example/controller/HelloServlet.class. An IDE like Eclipse, Netbeans or IntelliJ will do it all automatically when you've created a dynamic web project.

Note that the @WebServlet annotation only works on Java EE 6 / Servlet 3.0 capable containers (Tomcat 7, Glassfish 3, JBoss AS 6, etc) and if a /WEB-INF/web.xml file is present, then its <web-app> root declaration should comply Servlet 3.0 version as well.

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

</web-app>

If you're using/targeting an older Servlet version, such as Servlet 2.5, then you should remove the annotation and map the servlet in /WEB-INF/web.xml file as follows, which does effectively the same thing:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5"> 

    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>com.example.controller.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

Either way, it basically tells to the servlet container that it should do the following under the covers:

HelloServlet helloServlet = new HelloServlet(); // Construct servlet.
helloServlet.init(servletConfig); // Initialize servlet with config.
helloServlet.init(); // Initialize servlet without config.
servlets.put("/hello", helloServlet); // Add to servlet mapping.

Deploy the webapp and go to http://localhost:8080/contextname/hello (without .jsp extension!) to open the Hello World page. When you're opening the page like this, by entering URL in address bar or following a link or bookmark, then an HTTP GET request will be fired and the servlet's doGet() method will be called. When a form with method="post" is been submitted on the URL of the servlet, then an HTTP POST request will be fired and the servlet's doPost() method will be called.

Note that the JSP is been placed in /WEB-INF folder to prevent direct access to the JSP when a user enters its URL in the browser address bar. This is mandatory when it is required to invoke the servlet's doGet() method before the JSP is been displayed, for example when some data has to be preloaded.

Hello World #2 (preprocess a request)

Preprocessing a request such as preloading a list which is to be presented immediately on a "plain vanilla" GET request (which is used when you follow a link/bookmark or enter the URL in browser address yourself) is a less commonly known use case for a servlet. While it's used widely in the real world as well, the average basic Servlet tutorial found on the Internet does not explain this at all. However, it is pretty easy: you just have to implement the business job in the doGet() method instead of in doPost().

Here's a basic kickoff example where we're getting a list of products from the database so that it can be presented immediately when the end user opens the product page of a webshop. Only the ProductService class in the below example is another custom class and not described in this wiki since it's beyond the scope, but its list() method should be straightforward enough. The below example assumes it to be an EJB, but it can be anything, see also for example this post.

package com.example.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.business.ProductService;
import com.example.model.Product;

@WebServlet("/products")
public class ProductServlet extends HttpServlet {

    @EJB
    private ProductService productService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Preprocess request: load list of products for display in JSP.
        List<Product> products = productService.list();
        request.setAttribute("products", products);
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
    }
    
}

Here's how the /WEB-INF/products.jsp should look:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Our Products</title>
    </head>
    <body>
        <h1>Products</h1>
        <table>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Description</th>
                <th>Price</th>
            </tr>
            <c:forEach items="${products}" var="product">
                <tr>
                    <td>${product.id}</td>
                    <td><c:out value="${product.name}" /></td>
                    <td><c:out value="${product.description}" /></td>
                    <td><fmt:formatNumber value="${product.price}" type="currency" /></td>
                </tr>
            </c:forEach>
       </table>
    </body>
</html>

(the <c:out> is to protect your page against XSS while redisplaying user-controlled input, it does effectively the same thing as fn:escapeXml())

Deploy the webapp and go to http://localhost:8080/contextname/products (without the .jsp extension!). It'll call the doGet() method of the servlet which loads the products from the DB, stores it in the request scope and forwards the request/response to present the results.

To get a step further, you could filter the products based on a request parameter which is obtained from a GET search form as follows:

<form action="products">
    <input type="text" name="query" />
    <input type="submit" value="Search" />
</form>

or a hyperlink (or bookmark) as follows:

<a href="products?query=java">Search for products with keyword "java"</a>

with

String query = request.getParameter("query");
List<Product> products = productService.find(query);
// ...

This is also how search engines like Google work!

Coding style and recommendations

  • Do NOT call a doGet() method from a doPost() method or the other way around, or have them both call some other common method like processRequest(). This is wrong. Each of those two HTTP methods has its own clear responsibility: preprocessing or post-processing an HTTP request. If you intend to hook on all HTTP methods, you should be overriding the service() method. See also the Front Controller Pattern.

  • Do NOT output HTML in a servlet by using out.print() statements. It only makes it harder to maintain. HTML code belongs in JSP where you have the freedom to write HTML the way you want without fiddling with Java methods and quoted strings. From the other side on, do NOT use scriptlets (embedded raw Java code) inside JSP files. It only makes it harder to maintain. Java code belongs in Java classes where you have the freedom to write Java the way you want without fiddling with ugly <% %> things. See also How can I avoid Java code in JSP files, using JSP 2?

  • Do NOT use <jsp:useBean> if you're already using a servlet to process the model. It will only lead to confusion and maintenance trouble because the <jsp:useBean> follows a different level of MVC approach than when you're using servlets. It's either servlets or <jsp:useBean>, not both.

Specifications

Online Resources and tutorials

Frequently Asked Questions

Related tags

33264 questions
147
votes
8 answers

How do you remove a Cookie in a Java Servlet

How do you remove a cookie in a Java servlet? I tried this: http://www.jguru.com/faq/view.jsp?EID=42225 EDIT: The following now works successfully it appears to be the combination…
Dougnukem
  • 14,709
  • 24
  • 89
  • 130
144
votes
14 answers

Eclipse Build Path Nesting Errors

I'm working on a simple JSP/Servlet/Tomcat webapp for my class. The professor asked us to use a folder structure that is slightly different than the default dynamic web project structure. Rather than using the webcontent folder he wants all of our…
0xBrandon
  • 1,739
  • 3
  • 18
  • 21
143
votes
20 answers

How to differ sessions in browser-tabs?

In a web-application implemented in java using JSP and Servlets; if I store information in the user session, this information is shared from all the tabs from the same browser. How to differ sessions in the browser-tabs? In this example: <%@page…
Oriol Terradas
  • 1,788
  • 2
  • 19
  • 30
143
votes
9 answers

RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()

What is the conceptual difference between forward() and sendRedirect()?
RKCY
  • 4,095
  • 14
  • 61
  • 97
140
votes
11 answers

Simplest way to serve static data from outside the application server in a Java web application

I have a Java web application running on Tomcat. I want to load static images that will be shown both on the Web UI and in PDF files generated by the application. Also new images will be added and saved by uploading via the Web UI. It's not a…
Janne
  • 3,647
  • 7
  • 28
  • 34
138
votes
8 answers

Can I exclude some concrete urls from inside ?

I want some concrete filter to be applied for all urls except for one concrete (i.e. for /* except for /specialpath). Is there a possibility to do that? sample code: SomeFilter
Roman
  • 64,384
  • 92
  • 238
  • 332
134
votes
9 answers

Getting request payload from POST request in Java servlet

I have a javascript library that is sending a POST request to my Java servlet, but in the doPost method, I can't seem to get the contents of the request payload. In chrome Developer Tools, all the content is in the Request Payload section in the…
Fasih Awan
  • 1,891
  • 4
  • 17
  • 24
130
votes
11 answers

Spring get current ApplicationContext

I am using Spring MVC for my web application. My beans are written in "spring-servlet.xml" file Now I have a class MyClass and i want to access this class using spring bean In the spring-servlet.xml i have written following
LynAs
  • 6,407
  • 14
  • 48
  • 83
127
votes
2 answers

Recommended way to save uploaded files in a servlet application

I read here that one should not save the file in the server anyway as it is not portable, transactional and requires external parameters. However, given that I need a tmp solution for tomcat (7) and that I have (relative) control over the server…
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
126
votes
3 answers

Spring: how do I inject an HttpServletRequest into a request-scoped bean?

I'm trying to set up a request-scoped bean in Spring. I've successfully set it up so the bean is created once per request. Now, it needs to access the HttpServletRequest object. Since the bean is created once per request, I figure the container can…
Leonel
  • 28,541
  • 26
  • 76
  • 103
124
votes
9 answers

How to test my servlet using JUnit

I have created a web system using Java Servlets and now want to make JUnit testing. My dataManager is just a basic piece of code that submits it to the database. How would you test a Servlet with JUnit? My code example that allows a user to…
Lunar
  • 4,663
  • 7
  • 43
  • 51
122
votes
3 answers

ContextLoaderListener or not?

A standard spring web application (created by Roo or "Spring MVC Project" Template) create a web.xml with ContextLoaderListener and DispatcherServlet. Why do they not only use the DispatcherServlet and make it to load the complete configuration? I…
Ralph
  • 118,862
  • 56
  • 287
  • 383
122
votes
5 answers

How to solve javax.net.ssl.SSLHandshakeException Error?

I connected with VPN to setup the inventory API to get product list and it works fine. Once I get the result from the web-service and i bind to UI. And also I integrated PayPal with my application for make Express checkout when I make a call for…
selladurai
  • 6,491
  • 14
  • 56
  • 88
122
votes
2 answers

Why do Java webapps use .do extension? Where did it come from?

I have always wondered why so many Java developers use ".do" as the extension for their web controller (MVC) resources. Example: http://example.com/register.do It doesn't even seem to be framework specific as I have seen it in Spring MVC and Struts…
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
118
votes
19 answers

Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"

I have an HTML form in a JSP file in my WebContent/jsps folder. I have a servlet class servlet.java in my default package in src folder. In my web.xml it is mapped as /servlet. I have tried several URLs in action attribute of the HTML form:
pongahead
  • 1,984
  • 3
  • 18
  • 21