How do I use annotations to define Jakarta Servlet?

In Jakarta EE, you can define servlets using annotations instead of the traditional web.xml deployment descriptor. The most common annotation used for this purpose is @WebServlet. Here’s an overview of how to use annotations to define servlets:

1. Basic Syntax of the @WebServlet Annotation

The @WebServlet annotation is used to declare a servlet and map it to a URL pattern. It belongs to the jakarta.servlet.annotation package.

package org.kodejava.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "MyServlet", urlPatterns = {"/hello", "/greet"})
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello, World!</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().println("<h1>Post Request Handled</h1>");
    }
}

2. Parameters of @WebServlet

The @WebServlet annotation has several attributes you can set:

  1. name: Specifies the name of the servlet. This is optional.
  2. urlPatterns (or value): An array of URL patterns to which the servlet will respond. The urlPatterns or value element is required.
  3. loadOnStartup: Specifies the servlet’s load-on-startup priority. If set to a positive integer, the servlet will be loaded and initialized during deployment, not upon its first request.
  4. asyncSupported: A boolean indicating whether the servlet supports asynchronous processing. Default is false.

Example with Additional Attributes

package org.kodejava.servlet;

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

import java.io.IOException;

@WebServlet(
        name = "ExampleServlet",
        urlPatterns = "/example",
        loadOnStartup = 1,
        asyncSupported = true
)
public class ExampleServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");
        response.getWriter().println("Welcome to the Example Servlet!");
    }
}

3. How It Works

  • No web.xml Needed: When you use @WebServlet, there’s no need to register the servlet manually in web.xml. The application server automatically registers the servlet based on the annotation configuration.
  • URL Patterns: You define the URLs (using urlPatterns or value) to which the servlet will respond.

4. Multiple URL Patterns

You can map multiple URL patterns to the same servlet using an array:

package org.kodejava.servlet;

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

import java.io.IOException;

@WebServlet(urlPatterns = {"/path1", "/path2", "/path3"})
public class MultiPathServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");
        response.getWriter().println("This servlet can handle multiple paths!");
    }
}

5. Use with Filters and Listeners

Annotations can also be used for filters (@WebFilter) and listeners (@WebListener). For example:

  • @WebFilter for filters
  • @WebListener for event listeners

Conclusion

Using annotations to define servlets makes your code more concise and simplifies configuration. It eliminates the need for verbose web.xml entries and is easier to maintain, particularly in modern Jakarta EE-based applications.


Maven dependencies

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

Maven Central

How do I handle GET and POST requests in Jakarta Servlets?

Handling GET and POST requests in Jakarta Servlets involves overriding the doGet() and doPost() methods provided by the HttpServlet class. Here’s a step-by-step guide:


1. Import Necessary Packages

First, ensure you import the jakarta.servlet and jakarta.servlet.http packages in your servlet class.

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

2. Create a Servlet Class

Your servlet class should extend the HttpServlet class. The doGet() method will handle GET requests, while the doPost() method will handle POST requests.


3. Override doGet and doPost Methods

  • Use the HttpServletRequest object to get request data.
  • Use the HttpServletResponse object to send a response to the client.

4. Example Code

Here’s a complete example:

package org.kodejava.servlet;

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

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/example")  // Annotation to map this servlet to "/example"
public class ExampleServlet extends HttpServlet {

    // Handles GET requests
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Set response content type
        response.setContentType("text/html");

        // Get query parameter (e.g., ?name=John)
        String name = request.getParameter("name");

        // Prepare response
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello, " + (name != null ? name : "Guest") + "!</h1>");
        out.println("<form method='POST' action='/example'>");
        out.println("<label for='postName'>Enter your name:</label>");
        out.println("<input type='text' id='postName' name='name'>");
        out.println("<button type='submit'>Submit</button>");
        out.println("</form>");
        out.println("</body></html>");
    }

    // Handles POST requests
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Set response content type
        response.setContentType("text/html");

        // Get form data (e.g., from POST body)
        String name = request.getParameter("name");

        // Prepare response
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Thank you, " + (name != null ? name : "Guest") + "!</h1>");
        out.println("<a href='/example'>Go back</a>");
        out.println("</body></html>");
    }
}

5. Explanation

  • Annotations: The @WebServlet("/example") annotation maps this servlet to the /example URL.
  • GET and POST
    • The doGet() method handles requests sent as GET, typically used when the client fetches data.
    • The doPost() method handles requests sent as POST, commonly used to send form data to the server.
  • Parameters: Use request.getParameter("paramName") to retrieve parameters from the request.

6. Deploy and Test

  1. Add the servlet to your Jakarta EE web application.
  2. Access the servlet:
    • GET request: Open `http://localhost:8080/your-app-context/example` in a browser.
    • POST request: Submit the HTML form created in doGet() or use a tool like Postman.

7. Keynotes

  • Always handle exceptions (IOException and ServletException) properly in production.
  • Use appropriate HTTP response headers and status codes.
  • Consider character encoding (request.setCharacterEncoding("UTF-8") and response.setCharacterEncoding("UTF-8")) for supporting special characters.

This is how you handle GET and POST requests in a Jakarta Servlet effectively!

Maven dependencies

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

Maven Central

How do I create a basic servlet using the HttpServlet class?

To create a basic servlet using the HttpServlet class in Jakarta Servlet API, follow these steps:

Steps to Create a Basic Servlet:

  1. Create a Java Class Extending HttpServlet:
    • Your servlet class should extend the HttpServlet class provided in the Jakarta Servlet API.
  2. Define Servlet Annotations or Configuration:
    • Use the @WebServlet annotation to define the servlet and map it to a URL pattern. Alternatively, you can configure it in the web.xml file if annotations are not used.
  3. Override doGet or doPost Methods:
    • Override doGet for handling GET requests and doPost for POST requests (based on the type of request you expect).
  4. Set the Content Type in Response:
    • The response content type can be set using response.setContentType().
  5. Write the Response to Output:
    • Use a PrintWriter object received from response.getWriter() to write the response content.

Code Example:

Here’s a sample implementation for a basic servlet:

package org.kodejava.servlet;

import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "HelloWorldServlet", urlPatterns = {"/hello", "/helloworld"})
public class HelloWorld extends HttpServlet {

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      response.setContentType("text/html");

      PrintWriter writer = response.getWriter();
      writer.println("<html>");
      writer.println("<head><title>Hello World Servlet</title></head>");
      writer.println("<body>Hello World! How are you doing?</body>");
      writer.println("</html>");
      writer.close();
   }
}

Explanation of Code:

  1. @WebServlet Annotation:
    • name: Specifies the servlet name.
    • urlPatterns: Maps the servlet to specific URL patterns (in this example, /hello).
  2. doGet Method:
    • Handles GET requests sent to /hello.
    • Sets the content type for the response to text/html so that the client knows the returned content is HTML.
    • Dynamically writes an HTML page to the response using the PrintWriter.
  3. Response Lifecycle:
    • Any request to http://<server>:<port>/hello is routed to the doGet method based on the @WebServlet mapping.

Deploying the Servlet in Jakarta EE:

  • Place your servlet class in the Java package structure under src/main/java.
  • Ensure your project is configured to use a Jakarta Servlet container like Apache Tomcat or Jakarta EE compatible application server.
  • Deploy the .war file or run directly if your IDE supports it.

To build the .war file you can follow in steps in this post: How to build WAR file for Jakarta EE Servlet Container?.

Maven dependencies

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

Maven Central

How do I define a servlet with @WebServlet annotation?

Annotations is one new feature introduces in the Servlet 3.0 Specification. Previously to declare servlets, listeners or filters we must do it in the web.xml file. Now, with the new annotations feature we can just annotate servlet classes using the @WebServlet annotation.

package org.kodejava.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(
        name = "HelloAnnotationServlet",
        urlPatterns = {"/hello", "/helloanno"},
        asyncSupported = false,
        initParams = {
                @WebInitParam(name = "name", value = "admin"),
                @WebInitParam(name = "param1", value = "value1"),
                @WebInitParam(name = "param2", value = "value2")
        }
)
public class HelloAnnotationServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");

        PrintWriter out = response.getWriter();
        out.write("<html><head><title>WebServlet Annotation</title></head>");
        out.write("<body>");
        out.write("<h1>Servlet Hello Annotation</h1>");
        out.write("<hr/>");
        out.write("Welcome " + getServletConfig().getInitParameter("name"));
        out.write("</body></html>");
        out.close();
    }
}

After you’ve deploy the servlet you’ll be able to access it either using the /hello or /helloanno url.

The table below give brief information about the attributes accepted by the @WebServlet annotation and their purposes.

ATTRIBUTE DESCRIPTION
name The servlet name, this attribute is optional.
description The servlet description and it is an optional attribute.
displayName The servlet display name, this attribute is optional.
urlPatterns An array of url patterns use for accessing the servlet, this attribute is required and should at least register one url pattern.
asyncSupported Specifies whether the servlet supports asynchronous processing or not, the value can be true or false.
initParams An array of @WebInitParam, that can be used to pass servlet configuration parameters. This attribute is optional.
loadOnStartup An integer value that indicates servlet initialization order, this attribute is optional.
smallIcon A small icon image for the servlet, this attribute is optional.
largeIcon A large icon image for the servlet, this attribute is optional.

Maven dependencies

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

Maven Central