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
6 answers

Controlling the classpath in a servlet

My servlet application includes a number of library .jars, some of which contain embedded log4j.xml or log4j.properties files. I'd like to ensure that log4j finds my log4j.xml first! I've tried searching for some specification of the priorities of…
Ian Dickinson
  • 12,875
  • 11
  • 40
  • 67
7
votes
4 answers

ServerEndpoint and web.xml

I have some Soap, REST servlets and now one WebSocket: @ServerEndpoint("/game") public class WebSocketgame{ ... } I have next trouble: WebSocket dont visible, if web.xml is exists. In web.xml describes jdbc resources,servlets ant other... When i'm…
user1755546
  • 1,049
  • 2
  • 13
  • 27
7
votes
5 answers

Why HttpServletRequest.getRemoteAddr() doesn't work in Java servlet?

I'm developing a web app with java servlet, I hope to get the user ip info by calling request.getRemoteAddr() from inside processRequest(HttpServletRequest request,HttpServletResponse response). But it returns a wrong IP. Since I'm not very…
Frank
  • 30,590
  • 58
  • 161
  • 244
7
votes
1 answer

Storing username, pasword using cookies/sessions - Java Servlets

I am trying to create a registration page using servlets. I have created a basic HTML page which has a form with input for username and password. Now what I need to do is store the information submitted to the form using cookies/sessions. Then on…
newbdeveloper
  • 97
  • 2
  • 3
  • 12
7
votes
1 answer

What is a life of HttpServletRequest object?

I have doubt about HttpServletRequest life object. Is the request object destroyed after it got into controller?
Pravin Abhale
  • 395
  • 2
  • 4
  • 15
7
votes
2 answers

Java Servlet: Best Way to Determine if request is AJAX

What is the best way to determine whether a GET or POST request coming into a java servlet is an AJAX request? The method I've come across so far in my search is to strip the information out of the header with…
AJBradley
  • 185
  • 3
  • 12
7
votes
2 answers

Place the business logic in Java Beans?

I was reading this page and I found the following statement: MVC in Java Server Pages Now that we have a convenient architucture to separate the view, how can we leverage that? Java Server Pages (JSP) becomes more interesting because the…
Kiril
  • 39,672
  • 31
  • 167
  • 226
7
votes
2 answers

Asynchronous processing of Requests by Servlet

I came across the Asynchronous processing of requests by Servlets, as I was exploring how a NodeJS application and a Java application handles a request. From what I have read in different places: The request will be received and processed by a HTTP…
Sowmiya
  • 313
  • 2
  • 12
7
votes
3 answers

Can't Deserialize JSON in Java Servlet

My endpoint can't make sense of incoming JSON. Here's the endpoint: import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import…
Dingredient
  • 2,191
  • 22
  • 47
7
votes
1 answer

javax.servlet.* cannot be resolved to a type

I am running ubuntu 14.04 and eclipse Kepler (with java ee modules preloaded) , I am developing Dynamic Web App for first time, it always says javax.servlet.xyz cannot be resolved to a type please help I am including a screen snapshot for my error…
Chinmaya B
  • 405
  • 1
  • 7
  • 21
7
votes
3 answers

I want to use a method which is called only once after deploying to Server

I am new to Servlets. I want to use a method which is called only once after deploying to server. I looked at HttpServlet#init(). But I figured out it is called with each request. Did I misunderstand it? What are the alternatives to init()?
mebada
  • 2,252
  • 4
  • 27
  • 35
7
votes
5 answers

Mockito ArgumentCaptor gives NullpointerException on verify()

I'm currently trying to create tests for our Servlets. I've mocked HttpServletRequest, HttpServletResponse and an object serving as a database handler. In the test for the doPost method, my wish is to compare the values from the Json object and the…
frods
  • 311
  • 1
  • 3
  • 10
7
votes
2 answers

Explanation of context.xml

When using Tomcat, I've always treated web.xml as a kind of .htaccess or httpd.conf equivalent. It seems natural that there might have to be some way of configuring a web server. However, I don't quite understand the purpose of context.xml. For…
tau
  • 6,499
  • 10
  • 37
  • 60
7
votes
5 answers

JSR-356 WebSockets with Tomcat - How to limit connections within single IP address?

I made a JSR-356 @ServerEndpoint in which I want to limit alive connections from single IP address, to prevent simple DDOS attacks. Note that I'm search for Java solution (JSR-356, Tomcat or Servlet 3.0 specs). I have tried custom endpoint…
Piotr Müller
  • 5,323
  • 5
  • 55
  • 82
7
votes
3 answers

How to run different apps on single JBoss AS 6 instance behind different ports?

I am coming from this SO however my case is not on Tomcat, but JBoss EAP 6. So suppose I have two web apps app1 and app2 running on JBoss AS 6: app1 on http://localhost:8080/app1 app2 on http://localhost:8080/app2 However I want to configure…
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139