How do I use listeners like ServletContextListener for lifecycle management?

In Jakarta EE (formerly Java EE), you can use listeners like ServletContextListener to manage the lifecycle of a web application’s ServletContext. It provides hooks to execute logic during the initialization and destruction stages of the application. This can be useful for resource initialization, cleanup, or logging purposes.

Here’s how you can use ServletContextListener:


1. Implementing ServletContextListener

Create a class that implements the ServletContextListener interface. There are two main methods you can override:

  • contextInitialized(): This method is triggered when the ServletContext is initialized (before the web application starts serving requests).
  • contextDestroyed(): This method is triggered when the ServletContext is about to be destroyed (e.g., when the server shuts down or the application is undeployed).

Example

package org.kodejava.servlet;

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

@WebListener
public class AppLifecycleListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // Code to execute during application startup
        System.out.println("Web application starting up...");
        // Example: Initialize resources, setup logging, load configuration, etc.
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Code to execute during application shutdown
        System.out.println("Web application shutting down...");
        // Example: Release resources, close connections, etc.
    }
}

2. Registering the Listener

There are two ways to associate the listener with your web application:

a) Using the @WebListener Annotation

The simplest way is to annotate the class with @WebListener. This automatically registers the listener in your application without requiring any additional configuration.

@WebListener
public class AppLifecycleListener implements ServletContextListener {
    // Implementation as shown previously
}

b) Declaring in web.xml

Alternatively, you can declare the listener in the web.xml deployment descriptor:

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
    <listener>
        <listener-class>com.example.AppLifecycleListener</listener-class>
    </listener>
</web-app>

3. Common Use Cases

Here are a few common scenarios where you might use ServletContextListener:

  1. Loading Configuration Files: Load configuration settings from a file or database when the application starts.
    @Override
    public void contextInitialized(ServletContextEvent sce) {
       ServletContext context = sce.getServletContext();
       context.setAttribute("config", "some config value or object");
    }
    
  2. Resource Initialization and Cleanup: Initialize shared resources (e.g., database connections, thread pools) in contextInitialized() and close them in contextDestroyed().
    @Override
    public void contextInitialized(ServletContextEvent sce) {
       System.out.println("Initializing database connection...");
       // Initialize DB connection pool
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
       System.out.println("Closing database connection...");
       // Close DB connection pool
    }
    
  3. Setting Context Attributes: Use ServletContext object to set attributes accessible by the entire application.
    sce.getServletContext().setAttribute("appName", "My Application");
    
  4. Third-Party Integrations: Initialize third-party libraries or services during startup and dispose of them during shutdown.


Key Points to Remember

  • The contextInitialized() method is invoked before the application starts serving requests.
  • The contextDestroyed() method ensures proper cleanup when the application is shutting down.
  • Use the @WebListener annotation for easy configuration or declare the listener in web.xml for manual control.
  • Avoid long-running or blocking operations inside lifecycle methods as it might delay the application startup or shutdown process.

By efficiently using ServletContextListener, you can centralize important application lifecycle tasks and manage resources 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 count number of online users?

When you have a web application you might want to know how many users are currently online or connected to your website. If you have visited some web online forums you can see; usually on the first page; the list of their online users or maybe just the number of currently online users.

How do we know / count how many sessions or users are currently connected to our website. Do you care to know? Let’s see what Java Servlet API offers us on this matter.

Servlet API has an interface javax.servlet.http.HttpSessionListener, an implementation of this interface will have the ability to be notified by the servlet engine at anytime when a new session was created or destroyed.

This interface has two methods to be implemented; these methods are sessionCreated(HttpSessionEvent se) and sessionDestroyed(HttpSessionEvent se). These methods will be called as a notification that a new session was created, and the session was about to be destroyed respectively.

Now let’s create our session listener. The code below is what our class is going to be implemented.

package org.kodejava.servlet;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.ArrayList;

@WebListener
public class SessionCounter implements HttpSessionListener {
    public static final String COUNTER = "SESSION-COUNTER";
    private final List<String> sessions = new ArrayList<>();

    public void sessionCreated(HttpSessionEvent event) {
        System.out.println("SessionCounter.sessionCreated");
        HttpSession session = event.getSession();
        sessions.add(session.getId());
        session.setAttribute(SessionCounter.COUNTER, this);
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        System.out.println("SessionCounter.sessionDestroyed");
        HttpSession session = event.getSession();
        sessions.remove(session.getId());
        session.setAttribute(SessionCounter.COUNTER, this);
    }

    public int getActiveSessionNumber() {
        return sessions.size();
    }
}

To display information of current online users we need to create a simple JSP page. This JSP file will get the number of online user from HttpSession attribute named counter that we set in our listener above.

<%@ page import="org.kodejava.servlet.SessionCounter" %>
<html>
<head>
    <title>Session Counter</title>
</head>
<body>
<%
    SessionCounter counter = (SessionCounter) session.getAttribute(
            SessionCounter.COUNTER); 
%>

Number of online user(s): <%= counter.getActiveSessionNumber() %>
</body>
</html>

The final step to make the listener working is to register it in the web.xml file. Below is the example how to register the listener in web.xml.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <display-name>Servlet Examples</display-name>
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
</web-app>

Maven dependencies

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

Maven Central