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
7
votes
2 answers

Specify JRE/JDK when starting Apache Tomcat 7

Is there a way to tell Tomcat 7 the path to the JVM that must be used? For example: startup --jvm /path/to/my/jvm
MauroPorras
  • 5,079
  • 5
  • 30
  • 41
7
votes
1 answer

JSTL - use formatDate with a java.sql.Timestamp

I have a tag with the following: <%@ tag body-content="empty"%> <%@ attribute name="timestamp" required="true" type="java.sql.Timestamp"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib…
Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
7
votes
4 answers

How to call a servlet on jsp page load?

I have below servlet. I would like to call the servlet on jsp page load. How can I do that? servlet: SomeServlet.java Hello SomeServlet
user1016403
  • 12,151
  • 35
  • 108
  • 137
7
votes
3 answers

To embed OSGi in servlet container or servlet container in OSGi?

I need to reuse code originally developed for an Eclipse RCP app (i.e. boxed as Eclipse plugin/OSGi bundle) in a servlet. After reading a lot of blog posts, articles, wikis and so on I ended up at the point where I know that: An OSGi framework…
Matt Warrick
  • 1,385
  • 1
  • 13
  • 22
7
votes
6 answers

How to choose the max thread count for an HTTP servlet container?

I'm developing a restful Web service that runs as a servlet (using blocking IO) in Jetty. Figuring out the optimal setting for max threads seems hard. Is there a researched formula for deciding the max number of threads from some easily measurable…
hsivonen
  • 7,908
  • 1
  • 30
  • 35
7
votes
1 answer

Designer friendly JSP/Servlet web development in both Windows and Linux (Ubuntu, et. al.)

I'm a front-end developer for my college JSP project and so far I was using Sublime Text 2 for writing markup and my CSS/Less and ran the project directly from Apache Tomcat configured manually where I placed my project directory in webapps folder,…
Kushal
  • 3,112
  • 10
  • 50
  • 79
7
votes
2 answers

Why create new thread with startAsync instead of doing work in servlet thread?

In servlet 3.0 one can use startAsync to put long work in another thread, so that you can free up servlet thread. Seems that I'm missing something, because I don't see, why not just to use servlet thread for working? Is the thread created by…
Aivar
  • 6,814
  • 5
  • 46
  • 78
6
votes
3 answers

Correct way for parsing JSON objects containing arrays in Java Servlets (with Gson for example)

I know this is a topic much talked about, but I still wasn't able to find a correct and clear answer to my specific problem. I've got a JSON that looks like this: var myData = { "gameID" : gameID, "nrOfPlayers" : 2, …
Tõnis Pool
  • 185
  • 1
  • 3
  • 8
6
votes
2 answers

How can I retrieve the sub domain in a servlet? Does spring have any helpers

I first want to know if there is a built-in way of getting a subdomain from a url using pure servlets? And then if spring has any helpers? So my urls would be like: jonskeet.stackoverflow.com Where JonSkeet is the subdomain. I will create a filter…
Blankman
  • 259,732
  • 324
  • 769
  • 1,199
6
votes
2 answers

Filter is used as controller in Struts2

In struts2 why is a Filter is used as a controller instead of ActionServlet? What is the advantage of using a Filter over ActionServlet?
Sheo
  • 1,034
  • 12
  • 24
6
votes
2 answers

Cannot redirect with the response.sendRedirect

I googled and googled for hours on how to make a redirect in jsp or servlets. However when i try to apply it, it doesn't work. Code that i have inside jsp page: <% String articleId = request.getParameter("article_id").toString(); …
Dmitris
  • 3,408
  • 5
  • 35
  • 41
6
votes
1 answer

j_security_check redirect

I am learning Java servlets on Tomcat environment. I am learning how to use form based login authentication using j_security_check. So, in my servlet, I have a login page that has j_username and j_password. In web.xml file of that servlet, I have…
BlueChips23
  • 1,861
  • 5
  • 34
  • 53
6
votes
2 answers

404s when deploying a noir war to jetty on squeeze

I have a feeling I've missed something obvious here, but I don't know where to start looking. I have a fresh noir app, created thusly: $ lein noir new hiworld I add a new page handler to src/hiworld/server.clj: (ns hiworld.server (:require…
regularfry
  • 3,248
  • 2
  • 21
  • 27
6
votes
2 answers

what's the deal with Cookie.setMaxAge(Integer.MAX_VALUE)?

setMaxAge is supposed to control the maximum age of a cookie, so if my intention is to literally set the maximum age possible the logical thing would be doing: cookie.setMaxAge(Integer.MAX_VALUE); However this results in no Expires in cookie HTTP…
Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
6
votes
1 answer

Servlet. How to get parameters if their keys are not unique?

In servlet I get POST parameters where keys are not unique. Like this id = 12, id = 13, id = 14 So I can't use getParameterMap() to get this parameters (because HashMap contain only unique keys). What is the best way to solve this problem and get…
WelcomeTo
  • 19,843
  • 53
  • 170
  • 286
1 2 3
99
100