How do I share data between servlets using ServletContext?

In Java Servlets, you can share data between servlets using the ServletContext object. The ServletContext is an application-wide object that all servlets in a web application can access. It allows servlets to share information. Here’s how you can use it:


Steps to Share Data Using ServletContext:

  1. Set Attribute in ServletContext:
    • A servlet can store an object in the ServletContext as an attribute using the setAttribute method.
    ServletContext context = getServletContext();
    context.setAttribute("sharedData", "This is shared data");
    
  2. Retrieve the Attribute in Another Servlet:
    • Another servlet can retrieve the shared data using the getAttribute method.
    ServletContext context = getServletContext();
    String sharedData = (String) context.getAttribute("sharedData");
    
  3. (Optional) Remove the Attribute:
    • If needed, you can remove the attribute using the removeAttribute method.
    context.removeAttribute("sharedData");
    

Example Use Case:

Create two servlets: one for setting the data and one for retrieving it.

SetDataServlet.java

package org.kodejava.servlet;

import jakarta.servlet.ServletContext;
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("/setData")
public class SetDataServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Set shared data in ServletContext
        ServletContext context = getServletContext();
        context.setAttribute("sharedData", "Hello from SetDataServlet!");

        response.getWriter().println("Data set successfully.");
    }
}

GetDataServlet.java

package org.kodejava.servlet;

import jakarta.servlet.ServletContext;
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("/getData")
public class GetDataServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Retrieve shared data from ServletContext
        ServletContext context = getServletContext();
        String sharedData = (String) context.getAttribute("sharedData");

        response.getWriter().println("Shared Data: " + sharedData);
    }
}

Key Points:

  1. Application Scope:
    • Attributes in the ServletContext are available globally across the web application. They can be accessed by all servlets and JSPs.
  2. Thread-Safety:
    • Be cautious about thread safety because servlets handle multiple requests concurrently. If multiple threads modify the shared data simultaneously, data consistency issues may occur.
    • You may need to synchronize access to the shared object.
  3. Lifecycle:
    • Attributes in the ServletContext remain in memory until they are explicitly removed using removeAttribute, or the application is redeployed/stopped.

Advanced Sharing via ServletContextListener:

If you need to initialize or clean up shared data when the application starts or stops, you can use a ServletContextListener.

package org.kodejava.servlet;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;

@WebListener
public class AppContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        context.setAttribute("sharedData", "Initial shared data");
        System.out.println("Application started. Shared data set.");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Application stopped. Cleaning up...");
    }
}

This ensures shared data is set and removed in a centralized manner.


This approach to sharing data is straightforward and works seamlessly for many use cases in a web application.

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 initialize servlet parameters with ServletConfig?

You can initialize servlet parameters in a Java Servlet by using the ServletConfig object. The ServletConfig object contains initialization parameters and configuration data for a specific servlet. These parameters are specified in the web application’s deployment descriptor (web.xml file).

Here’s a step-by-step guide to using ServletConfig for initializing servlet parameters:


1. Define Initialization Parameters in web.xml

Define the initialization parameters for the servlet in the web.xml deployment descriptor using the <init-param> element inside the <servlet> element.

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" version="10">
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>org.kodejava.servlet.MyServlet</servlet-class>
        <init-param>
            <param-name>param1</param-name>
            <param-value>value1</param-value>
        </init-param>
        <init-param>
            <param-name>param2</param-name>
            <param-value>value2</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/myServlet</url-pattern>
    </servlet-mapping>
</web-app>

2. Implement the Servlet and Use ServletConfig

The servlet can retrieve these initialization parameters using the ServletConfig object. Typically, you retrieve ServletConfig in the init() method of the servlet.

Here’s an example:

package org.kodejava.servlet;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class MyServletConfig extends HttpServlet {

    private String param1;
    private String param2;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // Retrieve initialization parameters from ServletConfig
        param1 = config.getInitParameter("param1");
        param2 = config.getInitParameter("param2");

        // Log values (optional)
        System.out.println("Parameter 1: " + param1);
        System.out.println("Parameter 2: " + param2);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Use the initialized parameters
        resp.setContentType("text/plain");
        resp.getWriter().write("Param1: " + param1 + "\nParam2: " + param2);
    }
}

3. Access Parameters from ServletConfig

  • ServletConfig.getInitParameter(String name): Retrieves a single initialization parameter by its name.
  • ServletConfig.getInitParameterNames(): Returns an Enumeration of all defined parameter names.

For example:

Enumeration<String> parameterNames = config.getInitParameterNames();
while (parameterNames.hasMoreElements()) {
    String paramName = parameterNames.nextElement();
    System.out.println("Parameter Name: " + paramName + ", Value: " + config.getInitParameter(paramName));
}

Output

When you access the servlet (/myServlet), the servlet will use the parameters specified in the web.xml file and display:

Param1: value1
Param2: value2

This is how you can initialize servlet parameters using ServletConfig. It allows you to externalize configuration values, making them easier to modify without changing the servlet code.

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 cookies using Jakarta Servlet API?

Handling cookies in the Jakarta Servlet API is simple and straightforward. Cookies are small bits of data sent from a server to a client and then sent back by the client in subsequent requests to the server. Below is how you can handle cookies using Jakarta Servlet API:

1. Creating and Adding a Cookie

To create a cookie, use the jakarta.servlet.http.Cookie class. You can add the cookie to the response using the HttpServletResponse object.

Example: Adding a Cookie

package org.kodejava.servlet;

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

import java.io.IOException;

@WebServlet("/addCookie")
public class AddCookieServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
      // Create a new cookie
      Cookie cookie = new Cookie("username", "john_doe");

      // Set cookie properties
      cookie.setMaxAge(24 * 60 * 60); // 1 day (in seconds)
      cookie.setHttpOnly(true);      // Makes it inaccessible to JavaScript
      cookie.setSecure(true);        // Send it only over HTTPS

      // Add the cookie to the response
      response.addCookie(cookie);

      response.getWriter().println("Cookie has been set!");
   }
}

2. Reading Cookies

To read cookies, use the HttpServletRequest object to retrieve all cookies with the getCookies() method, and then search for the desired cookie.

Example: Retrieving a Cookie

package org.kodejava.servlet;

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

import java.io.IOException;

@WebServlet("/readCookie")
public class ReadCookieServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
      Cookie[] cookies = request.getCookies();

      if (cookies != null) {
         for (Cookie cookie : cookies) {
            if ("username".equals(cookie.getName())) {
               response.getWriter().println("Found cookie: "
                                            + cookie.getName() + " = "
                                            + cookie.getValue());
               return;
            }
         }
      }

      response.getWriter().println("Cookie not found!");
   }
}

3. Deleting a Cookie

To delete a cookie, set its maximum age to 0 and add it back to the response. When the browser sees the cookie with a 0 age, it will remove it.

Example: Deleting a Cookie

package org.kodejava.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class DeleteCookieServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
      Cookie[] cookies = request.getCookies();

      if (cookies != null) {
         for (Cookie cookie : cookies) {
            if ("username".equals(cookie.getName())) {
               Cookie deleteCookie = new Cookie("username", "");
               deleteCookie.setMaxAge(0);  // Mark cookie for deletion
               response.addCookie(deleteCookie);
               response.getWriter().println("Cookie has been deleted!");
               return;
            }
         }
      }

      response.getWriter().println("Cookie not found!");
   }
}

Important Notes

  1. Secure Cookies: Always mark cookies as secure (cookie.setSecure(true)) if you’re using HTTPS, to prevent transmission over unsecured connections.
  2. HttpOnly Flag: Use cookie.setHttpOnly(true) to prevent cookies from being accessed via client-side scripts, enhancing security.
  3. Path and Domain Settings: Cookies can be restricted to certain paths or domains to control their scope:
    cookie.setPath("/secure");
    cookie.setDomain(".example.com");
    
  4. Cookie Expiration:
    • cookie.setMaxAge(x): Sets the lifespan in seconds. x = 0 deletes the cookie, and x = -1 makes it a session cookie (deleted when the browser is closed).

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 set response headers with HttpServletResponse?

To set response headers using HttpServletResponse in a Java web application (e.g., within a servlet), you can use the setHeader or addHeader methods provided by the HttpServletResponse class. Here’s an overview of both methods and how to use them:

Methods for Setting Headers

  1. setHeader(String name, String value)
    • This method sets a response header with a given name and value.
    • If the header already exists, it replaces the existing value with the new one.
  2. addHeader(String name, String value)
    • This method allows you to add multiple values for the same header name.
    • If the header already exists, it adds the new value rather than replacing it.

Example Code

Below is an example of setting headers in a servlet:

package org.kodejava.servlet;

import java.io.IOException;

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

@WebServlet("/setHeaders")
public class HeaderServlet extends HttpServlet {

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {

      // Set Content-Type Header
      response.setContentType("text/html");

      // Set a custom response header
      response.setHeader("Custom-Header", "CustomValue");

      // Add multiple custom values for the same header name
      response.addHeader("Custom-Multi-Value-Header", "Value1");
      response.addHeader("Custom-Multi-Value-Header", "Value2");

      // Set Cache-Control Header
      response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

      // Set Expires Header
      response.setHeader("Expires", "0");

      // Write the response body
      response.getWriter().println("<h1>Response Headers Set</h1>");
   }
}

Important Notes

  • Setting Content-Type: Use setContentType(String type) to set the MIME type of the response body, like "text/html", "application/json", etc.
  • Overwriting Headers: Use setHeader if you want to ensure a header has only one value (overwriting any existing ones).
  • Adding Multiple Values: Use addHeader if the header allows multiple values (e.g., Set-Cookie).

Commonly Used Response Headers

Here are some commonly used headers for different scenarios:

  1. Caching:
    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    response.setHeader("Expires", "0");
    response.setHeader("Pragma", "no-cache");
    
  2. Content-Type and Encoding:
    response.setContentType("text/html");
    response.setCharacterEncoding("UTF-8");
    
  3. Custom Headers:
    response.setHeader("X-App-Name", "MyWebApplication");
    
  4. CORS (Cross-Origin Resource Sharing):
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type");
    

With this approach, you can control headers in your servlet responses 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 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 create zip file in Servlet for download?

The example below is a servlet that shows you how to create a zip file and send the generated zip file for user to download. The compressing process is done by the zipFiles method of this class.

For a servlet to work you need to configure it in the web.xml file of your web application which can be found after the code snippet below.

package org.kodejava.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@WebServlet(urlPatterns = "/zipservlet")
public class ZipDownloadServlet extends HttpServlet {
    public static final String FILE_SEPARATOR = System.getProperty("file.separator");

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            // The path below is the root directory of data to be
            // compressed.
            String path = getServletContext().getRealPath("data");

            File directory = new File(path);
            String[] files = directory.list();

            // Checks to see if the directory contains some files.
            if (files != null && files.length > 0) {

                // Call the zipFiles method for creating a zip stream.
                byte[] zip = zipFiles(directory, files);

                // Sends the response back to the user / browser. The
                // content for zip file type is "application/zip". We
                // also set the content disposition as attachment for
                // the browser to show a dialog that will let user 
                // choose what action will he do to the content.
                ServletOutputStream sos = response.getOutputStream();
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=\"DATA.ZIP\"");

                sos.write(zip);
                sos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Compress the given directory with all its files.
     */
    private byte[] zipFiles(File directory, String[] files) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(baos)) {
            byte[] bytes = new byte[2048];

            for (String fileName : files) {
                String path = directory.getPath() +
                        ZipDownloadServlet.FILE_SEPARATOR + fileName;
                try (FileInputStream fis = new FileInputStream(path);
                     BufferedInputStream bis = new BufferedInputStream(fis)) {

                    zos.putNextEntry(new ZipEntry(fileName));

                    int bytesRead;
                    while ((bytesRead = bis.read(bytes)) != -1) {
                        zos.write(bytes, 0, bytesRead);
                    }
                    zos.closeEntry();
                }
            }

            zos.close();
            return baos.toByteArray();
        }
    }
}

Maven dependencies

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

Maven Central

How do I create a hit counter servlet?

Here we have a simple example of creating a hit counter using servlet. The servlet updates the hits counter every time a page is visited and display the number of hits as an image. The image is generated at runtime using Java’s java.awt.Graphic2D and javax.imageio.ImageIO class.

To store the number of visit data we create a table hit_counter with a single field called counter and set the initial value of the counter to zero. Below is the HitCounterServlet servlet code.

package org.kodejava.servlet;

import javax.imageio.ImageIO;
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 java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.*;

@WebServlet(name = "HitCounterServlet", urlPatterns = "/hitcounter")
public class HitCounterServlet extends HttpServlet {
    private static final String URL = "jdbc:mysql://localhost/kodejava";
    private static final String USERNAME = "kodejava";
    private static final String PASSWORD = "s3cr*t";

    @Override
    public void init() throws ServletException {
        super.init();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        updateHitCounter();
        getHitCounterImage(response);
    }

    private void updateHitCounter() {
        try (Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
            // Update the hits counter table by incrementing the
            // counter every time a user hits our page.
            String sql = "UPDATE hit_counter SET counter = counter + 1";
            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void getHitCounterImage(HttpServletResponse response) throws IOException {
        String hits = "";
        try (Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
            // Get the current hits counter from database.
            String sql = "SELECT counter FROM hit_counter";
            PreparedStatement stmt = connection.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                hits = rs.getString("counter");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        // Create an image of our counter to be sent to the browser.
        BufferedImage buffer = new BufferedImage(100, 20, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffer.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(new Font("Roboto", Font.BOLD, 20));
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 100, 30);
        g.setColor(Color.BLACK);
        g.drawString(hits, 0, 20);

        response.setContentType("image/png");
        OutputStream os = response.getOutputStream();
        ImageIO.write(buffer, "png", os);
        os.close();
    }
}

To display the hits counter image on the JSP page, create an img tag with the source (src) point to our HitCounterServlet servlet url.

Visited for: <img src="http://localhost:8080/hitcounter" alt="Hit Counter"/> times.

Maven dependencies

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.1.0</version>
    </dependency>
</dependencies>

Maven Central Maven Central

How do I create a HelloWorld Servlet?

Servlet is a Java solution for creating a dynamic web application, it can be compared with the old CGI technology. Using Servlet we can create a web application that can display information from a database, receive information from a web form to be stored in the application database.

This example shows the very basic of servlet, it returns a hello world html document for the browser. At the very minimum a servlet will have a doPost() and doGet() method which handles the HTTP POST and GET request.

package org.kodejava.servlet;

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 = "HelloWorldServlet", urlPatterns = {"/hello", "/helloworld"})
public class HelloWorld extends HttpServlet {

    public HelloWorld() {
        super();
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res)
            throws IOException {
        doPost(req, res);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res)
            throws IOException {
        res.setContentType("text/html");

        PrintWriter writer = res.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();
    }
}

When the servlet is deployed to the container we can access it from an url in a form of http://localhost:8080/app-name/helloworld.

Maven dependencies

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

Maven Central