Context & Deployment

Getting your Java application running

← Back to Index

What is a Web Application Context?

A context represents a single web application running within a servlet container. Understanding contexts is essential because it determines how your application is accessed (its URL path), how it's isolated from other applications, and how it can be configured and deployed.

Each context:

Apartment Building Analogy:

Think of a servlet container (like Tomcat) as an apartment building:

  • The entire building = Tomcat server
  • Individual apartments = Web application contexts
  • Apartment number (101, 102...) = Context path (/app1, /app2)
  • Each apartment has its own furniture = Each context has its own classes
  • Apartments share building utilities = Contexts share container services

Context Path Explained

The context path is the URL prefix that identifies your application:

http://localhost:8080/myapp/products/list
└──────────────────┘└─────┘└────────────┘
     Host:Port      Context   Servlet
                     Path     Path

# If your WAR is named "myapp.war":
# Context path = /myapp

# URL breakdown:
# http://localhost:8080  → Tomcat server
# /myapp                 → Your application (context)
# /products/list         → Servlet/resource within your app

The ServletContext Object

Every web application has a ServletContext object—the programmatic representation of the context:

public class MyServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        ServletContext ctx = getServletContext();

        // 1. Access initialization parameters (from web.xml)
        String dbUrl = ctx.getInitParameter("database.url");
        String adminEmail = ctx.getInitParameter("admin.email");

        // 2. Store application-wide data (shared across all servlets)
        DataSource ds = createDataSource(dbUrl);
        ctx.setAttribute("dataSource", ds);

        // 3. Get real file paths
        String uploadDir = ctx.getRealPath("/uploads");
        // Returns: C:\tomcat\webapps\myapp\uploads

        // 4. Get resource as stream
        InputStream config = ctx.getResourceAsStream("/WEB-INF/config.properties");

        // 5. Get context information
        String serverInfo = ctx.getServerInfo();  // "Apache Tomcat/10.1.x"
        String contextPath = ctx.getContextPath(); // "/myapp"

        // 6. Log messages
        ctx.log("Application initialized successfully");
    }
}

Attribute Scopes

Scope Object Lifetime Use For
Application ServletContext Entire app lifetime Config, shared resources, caches
Session HttpSession User session Login state, shopping cart
Request HttpServletRequest Single request Form data, request params

Deployment Methods

Method 1: WAR File Deployment (Most Common)

# For Tomcat, copy WAR to webapps directory:
cp myapp.war $CATALINA_HOME/webapps/

# Tomcat automatically:
# 1. Detects the new WAR file
# 2. Extracts it to webapps/myapp/
# 3. Deploys and starts the application
# 4. Application available at /myapp

# To undeploy:
rm $CATALINA_HOME/webapps/myapp.war
# Tomcat removes the extracted directory

Context Path from WAR Name:

WAR File Name Context Path Access URL
myapp.war /myapp http://localhost:8080/myapp/
ROOT.war / (root) http://localhost:8080/
app#v1.war /app/v1 http://localhost:8080/app/v1/

Method 2: Exploded Directory

# Instead of myapp.war, create a directory:
webapps/
└── myapp/
    ├── WEB-INF/
    │   ├── web.xml
    │   ├── classes/
    │   └── lib/
    ├── index.html
    └── css/

# Benefits:
# - Edit files without rebuilding WAR
# - Faster deployment cycle during development
# - Can modify JSPs and see changes immediately

Method 3: Context XML Files

<!-- $CATALINA_HOME/conf/Catalina/localhost/myapp.xml -->
<Context docBase="/path/to/myapp.war" reloadable="false">

    <!-- Database connection pool -->
    <Resource name="jdbc/MyDB"
              auth="Container"
              type="javax.sql.DataSource"
              maxTotal="100"
              maxIdle="30"
              username="dbuser"
              password="dbpass"
              driverClassName="com.mysql.cj.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/mydb"/>

    <!-- Environment entries -->
    <Environment name="maxUploadSize"
                 value="10485760"
                 type="java.lang.Integer"/>

</Context>

Method 4: Tomcat Manager

# 1. Configure manager user in tomcat-users.xml:
<user username="admin"
      password="secret"
      roles="manager-gui,manager-script"/>

# 2. Access Manager at:
http://localhost:8080/manager/html

# 3. Or use the text interface (for scripting):
curl -u admin:secret \
     -T myapp.war \
     "http://localhost:8080/manager/text/deploy?path=/myapp"

Method 5: Maven Plugin

<!-- pom.xml -->
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <configuration>
        <url>http://localhost:8080/manager/text</url>
        <server>TomcatServer</server>
        <path>/myapp</path>
    </configuration>
</plugin>

# Deploy commands:
mvn tomcat7:deploy      # First deployment
mvn tomcat7:redeploy    # Update existing
mvn tomcat7:undeploy    # Remove

JNDI Resources

JNDI (Java Naming and Directory Interface) allows you to look up resources configured in the container:

// Looking up a DataSource configured in context.xml:
public class DatabaseServlet extends HttpServlet {

    private DataSource dataSource;

    @Override
    public void init() throws ServletException {
        try {
            // Look up the JNDI resource
            Context initCtx = new InitialContext();
            Context envCtx = (Context) initCtx.lookup("java:comp/env");
            dataSource = (DataSource) envCtx.lookup("jdbc/MyDB");
        } catch (NamingException e) {
            throw new ServletException("Cannot find DataSource", e);
        }
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        try (Connection conn = dataSource.getConnection()) {
            // Use the connection...
        } catch (SQLException e) {
            resp.sendError(500, "Database error");
        }
    }
}

Hot Deployment

Hot deployment means updating an application without restarting the entire server.

<!-- In context.xml or server.xml -->
<Context reloadable="true">
    <!-- Monitor WEB-INF/classes and WEB-INF/lib for changes -->
</Context>

<!-- In server.xml Host element -->
<Host name="localhost" appBase="webapps"
      unpackWARs="true"       <!-- Extract WAR files -->
      autoDeploy="true">      <!-- Watch for new WARs -->
</Host>
Setting What it Does Use In
reloadable="true" Reload when classes change Development only!
autoDeploy="true" Deploy new WARs automatically Development, staging
unpackWARs="true" Extract WAR to directory Usually always
Production Warning

Never use reloadable="true" in production!

  • Causes memory leaks (old classloaders not garbage collected)
  • CPU overhead from watching files
  • Unpredictable reload timing

Production Deployment Strategies

Strategy 1: Stop-Deploy-Start

# Simple approach with brief downtime
curl "http://localhost:8080/manager/text/stop?path=/myapp"
curl -T myapp.war "http://localhost:8080/manager/text/deploy?path=/myapp&update=true"
curl "http://localhost:8080/manager/text/start?path=/myapp"

Strategy 2: Parallel Deployment (Zero Downtime)

# Tomcat 7+ supports multiple versions running simultaneously
# Version naming: appname##version.war

myapp##001.war    # Version 001
myapp##002.war    # Version 002

# How it works:
# - Existing sessions continue on old version
# - New sessions go to newest version
# - Old version undeploys when all sessions end

Strategy 3: Blue-Green Deployment

# Run two identical environments:
# BLUE (v1.0) - Currently active
# GREEN (v1.1) - Standby

# Deployment steps:
# 1. Deploy v1.1 to GREEN
# 2. Test GREEN thoroughly
# 3. Switch load balancer to GREEN
# 4. If problems, instantly switch back to BLUE

Classloading and Isolation

Each context has its own classloader, providing isolation between applications:

// Classloader hierarchy:
Bootstrap ClassLoader
    └── System ClassLoader (Tomcat startup)
        └── Common ClassLoader ($CATALINA_HOME/lib)
            ├── WebApp1 ClassLoader (WEB-INF/classes, lib)
            ├── WebApp2 ClassLoader (WEB-INF/classes, lib)
            └── WebApp3 ClassLoader (WEB-INF/classes, lib)

// Each app has its own classloader:
// - Classes in WEB-INF/classes take precedence
// - Apps can use different library versions
// - Apps are isolated from each other

Preventing Memory Leaks

// Use a ServletContextListener to cleanup:
@WebListener
public class CleanupListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // CRITICAL: Clean up to prevent memory leaks

        // 1. Stop any threads you started
        executorService.shutdown();

        // 2. Deregister JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
            } catch (SQLException e) {
                log.warn("Error deregistering driver", e);
            }
        }

        // 3. Close cached connections/resources
        connectionPool.close();
    }
}

Spring Boot Context Configuration

Spring Boot simplifies context configuration in application.properties:

# application.properties

# Context path (default is /)
server.servlet.context-path=/myapp

# Server port
server.port=8080

# Session configuration
server.servlet.session.timeout=30m
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

# Embedded Tomcat settings
server.tomcat.max-threads=200
server.tomcat.min-spare-threads=10

Summary

  • Context: A single web application instance within a container
  • Context Path: The URL prefix that identifies your application
  • ServletContext: Programmatic access to context information and resources
  • Deployment Methods: WAR drop, Manager app, Maven plugins, context XML
  • JNDI Resources: Container-managed database pools and other resources
  • Hot Deployment: Development convenience, never for production
  • Production Strategies: Blue-green, rolling, parallel deployment
  • Classloader Isolation: Each context has its own classloader
  • Memory Leaks: Clean up resources in contextDestroyed()