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
115
votes
10 answers

How to use Session attributes in Spring-mvc

Could you help me write spring mvc style analog of this code? session.setAttribute("name","value"); And how to add an element that is annotated by @ModelAttribute annotation to session and then get access to it?
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
110
votes
5 answers

doGet and doPost in Servlets

I've developed an HTML page that sends information to a Servlet. In the Servlet, I am using the methods doGet() and doPost(): public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String id…
dedalo
  • 2,541
  • 12
  • 32
  • 34
110
votes
9 answers

java.lang.IllegalStateException: Cannot (forward | sendRedirect | create session) after response has been committed

This method throws java.lang.IllegalStateException: Cannot forward after response has been committed and I am unable to spot the problem. Any help? int noOfRows = Integer.parseInt(request.getParameter("noOfRows")); String chkboxVal = ""; …
109
votes
14 answers

Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?

I'm writing a Spring MVC application deployed on Tomcat. See the following minimal, complete, and verifiable example public class Application extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class[]…
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
109
votes
13 answers

Http Servlet request lose params from POST body after read it once

I'm trying to access two http request parameters in a Java Servlet filter, nothing new here, but was surprised to find that the parameters have already been consumed! Because of this, they are not available in the filter chain anymore. It seems that…
amuniz
  • 3,292
  • 2
  • 20
  • 22
106
votes
6 answers

Get JSF managed bean by name in any Servlet related class

I'm trying to write a custom servlet (for AJAX/JSON) in which I would like to reference my @ManagedBeans by name. I'm hoping to map: http://host/app/myBean/myProperty to: @ManagedBean(name="myBean") public class MyBean { public String…
Konrad Garus
  • 53,145
  • 43
  • 157
  • 230
104
votes
5 answers

How to run a background task in a servlet based web application?

I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users…
104
votes
7 answers

Prevent user from seeing previously visited secured page after logout

I have the requirement that the end user should not be able to go back to the restricted page after logout/sign out. But currently the end user is able to do that by the browser back button, visiting browser history or even by re-entering the URL in…
raaz
  • 12,410
  • 22
  • 64
  • 81
103
votes
5 answers

what is the difference between a portlet and a servlet?

I am asked to work on portlets and portals. I want to know the difference between a portlet and a servlet? How / where does a portlet differ (may be functionally) from a servlet?
Rajesh
  • 1,033
  • 2
  • 8
  • 6
100
votes
6 answers

Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()?

In Java Servlets, one can access the response body via response.getOutputStream() or response.getWriter(). Should one call .close() on this OutputStream after it has been written to? On the one hand, there is the Blochian exhortation to always close…
Steven Huwig
  • 20,015
  • 9
  • 55
  • 79
99
votes
5 answers

init-param and context-param

What is the difference between and !?
mina
  • 1,872
  • 1
  • 15
  • 20
98
votes
6 answers

HttpServletRequest - Get query string parameters, no form data

In HttpServletRequest, getParameterMap returns a Map of all query string parameters and post data parameters. Is there a way to get a Map of ONLY query string parameters? I'm trying to avoid using getQueryString and parsing out the values.
JasonStoltz
  • 3,040
  • 4
  • 27
  • 37
98
votes
4 answers

What are the differences between Servlet 2.5 and 3?

I'm rolling J2EE code that adheres to Servlet 2.5 and I'm wondering what are the major differences between 2.5 and 3. Pointers to official Sun docs and personal experiences are most appreciated. If I shouldn't be concerning myself with 3 for the…
Max A.
  • 4,842
  • 6
  • 29
  • 27
96
votes
8 answers

Google Recaptcha v3 example demo

Until now, I was working with Google Recaptcha v2, but now I want to update my WebApp using the lastest version (v3). Is it possible to anyone add a fully working Google Recaptcha v3 example for a basic form as I can't find any working demos of…
Ommadawn
  • 2,450
  • 3
  • 24
  • 48
95
votes
4 answers

Servlet Filter: How to get all the headers from servletRequest?

Here is how my WebFilter looks like @WebFilter("/rest/*") public class AuthTokenValidatorFilter implements Filter { @Override public void init(final FilterConfig filterConfig) throws ServletException { } @Override public void…
daydreamer
  • 87,243
  • 191
  • 450
  • 722