What is an Application Server?

Understanding the runtime environment for your Java applications

← Back to Index

Introduction: Where Does Your Code Actually Run?

When you write a Java web application, you create classes, controllers, services, and HTML templates. But have you ever wondered: what actually runs your code? When a user visits your website, something needs to:

This "something" is an Application Server (or a simpler variant called a Web Server or Servlet Container). It's the runtime environment that hosts your application and handles all the low-level networking, protocol parsing, and lifecycle management so you can focus on writing business logic.

A Simple Analogy: The Restaurant

Think of deploying a web application like opening a restaurant:

An Application Server is software that provides the runtime environment for applications. For Java web applications, it:

  • Listens for incoming network connections (typically HTTP on port 80/443 or 8080)
  • Manages the lifecycle of your application (loading, starting, stopping)
  • Provides services like connection pooling, transactions, security, and more
  • Executes your code when requests arrive
  • Handles multiple concurrent users efficiently

Web Server vs Application Server vs Servlet Container

These terms are often used interchangeably, but they have distinct meanings. Understanding the differences helps you choose the right tool.

Web Server

A Web Server serves static content (HTML, CSS, JavaScript, images) and handles HTTP protocol basics. It's like a file server that speaks HTTP.

// Web servers serve STATIC content
// They read files from disk and send them over HTTP

User requests: GET /index.html
Web server: Reads /var/www/index.html from disk
Web server: Sends file content back with HTTP headers

// Examples of pure web servers:
// - Apache HTTP Server (httpd)
// - Nginx
// - Microsoft IIS (for static content)

// Web servers are FAST for static files
// But they can't run your Java code!

Servlet Container (Web Container)

A Servlet Container extends the web server concept by adding the ability to run Java Servlets. It implements the Java Servlet specification, allowing dynamic content generation.

// Servlet containers can run Java code!
// They implement the Servlet specification

User requests: GET /api/users
Servlet container:
  1. Parses HTTP request
  2. Creates HttpServletRequest object
  3. Finds matching Servlet (@WebServlet or mapping in web.xml)
  4. Calls servlet.service(request, response)
  5. Your Java code executes!
  6. Sends HttpServletResponse back to user

// Examples of Servlet containers:
// - Apache Tomcat (most popular)
// - Eclipse Jetty
// - Undertow (used in WildFly)

// Servlet containers implement:
// - Jakarta Servlet specification
// - Jakarta Server Pages (JSP)
// - Jakarta WebSocket

Application Server (Full Jakarta EE)

A Full Application Server includes everything a servlet container has, PLUS additional enterprise services defined by the Jakarta EE (formerly Java EE) specification.

// Application servers provide the FULL Jakarta EE stack

// Everything in a Servlet Container, PLUS:
// - EJB (Enterprise JavaBeans) container
// - JPA (Java Persistence API) integration
// - JTA (Java Transaction API)
// - JMS (Java Message Service)
// - CDI (Contexts and Dependency Injection)
// - JAX-RS (RESTful Web Services)
// - Jakarta Security
// - And much more...

// Examples of full application servers:
// - WildFly (formerly JBoss)
// - Payara (GlassFish fork)
// - IBM WebSphere Liberty
// - Oracle WebLogic
// - Apache TomEE (Tomcat + EE)
Feature Web Server Servlet Container Application Server
Static Content Yes Yes Yes
Servlets/JSP No Yes Yes
EJB No No Yes
JMS No No Yes
JTA Transactions No No Yes
Examples Nginx, Apache Tomcat, Jetty WildFly, WebLogic
Complexity Low Medium High
Resource Usage Low Medium High

What About Spring Boot?

If you've used Spring Boot, you might be confused—you don't deploy to an external server; you just run a JAR file! This is because Spring Boot takes a different approach: embedded servers.

Traditional Deployment (External Server)

// Traditional approach: Deploy WAR to external server

// 1. You build a WAR file
mvn package
// Output: myapp.war

// 2. You have a server installed separately
//    /opt/tomcat/

// 3. You deploy by copying WAR to server
cp myapp.war /opt/tomcat/webapps/

// 4. Server detects and deploys your app
//    Available at: http://localhost:8080/myapp

// The server exists OUTSIDE your application
┌─────────────────────────────────────────┐
│           TOMCAT SERVER                  │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐   │
│  │ myapp   │ │ other   │ │ another │   │
│  │  .war   │ │  .war   │ │  .war   │   │
│  └─────────┘ └─────────┘ └─────────┘   │
│                                         │
│  One server hosts MULTIPLE applications │
└─────────────────────────────────────────┘

Spring Boot (Embedded Server)

// Spring Boot approach: Server is INSIDE your application

// 1. You build an executable JAR
mvn package
// Output: myapp.jar (includes Tomcat inside!)

// 2. You just run it!
java -jar myapp.jar
// Available at: http://localhost:8080

// The server is EMBEDDED in your application
┌─────────────────────────────────────────┐
│              myapp.jar                   │
│  ┌─────────────────────────────────┐    │
│  │     YOUR APPLICATION CODE       │    │
│  │   (Controllers, Services, etc.) │    │
│  └─────────────────────────────────┘    │
│  ┌─────────────────────────────────┐    │
│  │     EMBEDDED TOMCAT             │    │
│  │   (Inside your JAR file!)       │    │
│  └─────────────────────────────────┘    │
│                                         │
│  Self-contained, runs anywhere with JVM │
└─────────────────────────────────────────┘

Why Embedded Servers Became Popular

Aspect External Server Embedded Server (Spring Boot)
Deployment Copy WAR to server Just run the JAR
Configuration Server + App configured separately All in one place
Server Version Whatever's installed on server You control it (in pom.xml)
Multiple Apps Many apps on one server One app per process
Docker Friendly More complex Very easy
Cloud Native Traditional Modern, 12-factor
Startup Time Server already running Server starts with app
Modern Reality

Today, most new Java applications use embedded servers (Spring Boot, Quarkus, Micronaut). External application servers are still used in large enterprises with existing infrastructure, or when you need full Jakarta EE features that embedded servers don't provide.

How an Application Server Handles Requests

Let's trace what happens when a user requests a page from your Java web application:

// User types: http://myapp.com/products/123
// Here's what happens inside the application server:

┌─────────────────────────────────────────────────────────────────────┐
│                     APPLICATION SERVER                               │
│                                                                      │
│  1. CONNECTOR (Listens on port 8080)                                │
│     ┌─────────────────────────────────────────────────────────┐     │
│     │  - Accepts TCP connection from browser                   │     │
│     │  - Reads raw bytes from network                         │     │
│     │  - Parses HTTP protocol                                 │     │
│     │  - Creates internal request object                       │     │
│     └─────────────────────────────────────────────────────────┘     │
│                              │                                       │
│                              ▼                                       │
│  2. ENGINE (Request Processing)                                      │
│     ┌─────────────────────────────────────────────────────────┐     │
│     │  - Determines which Host (virtual host) handles request │     │
│     │  - Determines which Context (application) handles it    │     │
│     │  - Determines which Servlet handles the URL pattern     │     │
│     └─────────────────────────────────────────────────────────┘     │
│                              │                                       │
│                              ▼                                       │
│  3. FILTER CHAIN                                                     │
│     ┌─────────────────────────────────────────────────────────┐     │
│     │  Security Filter → Logging Filter → CORS Filter → ...   │     │
│     └─────────────────────────────────────────────────────────┘     │
│                              │                                       │
│                              ▼                                       │
│  4. YOUR SERVLET (or Spring Controller)                              │
│     ┌─────────────────────────────────────────────────────────┐     │
│     │  @GetMapping("/products/{id}")                          │     │
│     │  public Product getProduct(@PathVariable Long id) {     │     │
│     │      return productService.findById(id);                │     │
│     │  }                                                       │     │
│     └─────────────────────────────────────────────────────────┘     │
│                              │                                       │
│                              ▼                                       │
│  5. RESPONSE (travels back through filters, connector, to browser)  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Key Components Explained

Services Provided by Application Servers

Application servers do much more than just route HTTP requests. They provide many services that your application can use:

1. Connection Pooling

// Problem: Creating database connections is SLOW (100-500ms each)
// Solution: Server maintains a pool of ready connections

// Without pooling:
public List<User> getUsers() {
    Connection conn = DriverManager.getConnection(url, user, pass); // SLOW!
    // ... query ...
    conn.close(); // Connection destroyed, next request creates new one
}

// With pooling (configured in server):
@Resource
DataSource dataSource;  // Server manages the pool

public List<User> getUsers() {
    Connection conn = dataSource.getConnection(); // FAST! Gets existing connection
    // ... query ...
    conn.close(); // Returns to pool, doesn't destroy
}

// Server configuration (context.xml in Tomcat):
<Resource name="jdbc/mydb"
          type="javax.sql.DataSource"
          maxTotal="100"           <!-- Max 100 connections -->
          maxIdle="30"             <!-- Keep 30 ready -->
          maxWaitMillis="10000"/>  <!-- Wait max 10s for connection -->

2. Thread Management

// Server manages a thread pool for handling requests

// Each request gets a thread from the pool
// You don't create threads manually!

┌─────────────────────────────────────────┐
│           THREAD POOL                    │
│  ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐        │
│  │ T1│ │ T2│ │ T3│ │...│ │T200│        │
│  └───┘ └───┘ └───┘ └───┘ └───┘        │
│    │     │     │                        │
│    ▼     ▼     ▼                        │
│  Req1  Req2  Req3   (requests assigned) │
└─────────────────────────────────────────┘

// Tomcat default: 200 threads max
// If 201 requests come simultaneously, one waits

// Configuration (server.xml):
<Connector port="8080"
           maxThreads="200"
           minSpareThreads="10"
           acceptCount="100"/>

3. Session Management

// Server tracks user sessions across requests

@GetMapping("/cart")
public Cart getCart(HttpSession session) {
    // Server automatically:
    // 1. Reads JSESSIONID cookie from request
    // 2. Looks up session data in memory
    // 3. Provides it to your code

    Cart cart = (Cart) session.getAttribute("cart");
    return cart;
}

// Session configuration (web.xml):
<session-config>
    <session-timeout>30</session-timeout>  <!-- 30 minutes -->
    <cookie-config>
        <http-only>true</http-only>
        <secure>true</secure>
    </cookie-config>
</session-config>

4. Security

// Server can handle authentication and authorization

// web.xml security configuration:
<security-constraint>
    <web-resource-collection>
        <url-pattern>/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/error.html</form-error-page>
    </form-login-config>
</login-config>

5. JNDI (Java Naming and Directory Interface)

// Server provides a registry for looking up resources
// Your app doesn't hardcode connection strings!

// In your code - just look up by name:
@Resource(name = "jdbc/productionDB")
DataSource dataSource;

// Server configures the ACTUAL connection:
// Development server → points to dev database
// Production server → points to production database
// Same code, different configuration!

Popular Application Servers

Servlet Containers (Lightweight)

Server Description Best For
Apache Tomcat Most popular, reference implementation Most Java web apps, Spring Boot default
Eclipse Jetty Lightweight, embeddable, fast startup Microservices, embedded scenarios
Undertow High performance, non-blocking High-concurrency applications

Full Application Servers (Jakarta EE)

Server Description Best For
WildFly Free, open source, formerly JBoss AS Full Jakarta EE, enterprise apps
Payara GlassFish fork, production-focused Jakarta EE with support options
IBM WebSphere Liberty Commercial, modular, fast Enterprise, IBM ecosystem
Oracle WebLogic Commercial, full-featured Large enterprise, Oracle ecosystem
Apache TomEE Tomcat + Jakarta EE Familiar Tomcat with EE features

Choosing the Right Server

Use a Servlet Container (Tomcat/Jetty) when:

  • Building with Spring Boot (embedded server)
  • You don't need EJB or JMS
  • You want lightweight and simple
  • Building microservices
  • Deploying to containers (Docker, Kubernetes)

Use a Full Application Server when:

  • Required by company policy/infrastructure
  • Need full Jakarta EE features (EJB, JMS, etc.)
  • Multiple applications sharing resources
  • Enterprise support contracts required
  • Migrating legacy Java EE applications

Use Embedded Server (Spring Boot) when:

  • Building new applications
  • Want simple deployment (just run JAR)
  • Building for the cloud
  • Want to control server version
  • Doing microservices architecture

Summary

  • Application Server: Runtime environment that hosts and executes your Java web applications
  • Web Server: Serves static content only (Nginx, Apache HTTP Server)
  • Servlet Container: Runs Servlets/JSP (Tomcat, Jetty)
  • Full Application Server: Complete Jakarta EE implementation (WildFly, WebLogic)
  • Embedded Server: Server packaged inside your application (Spring Boot approach)
  • Services: Connection pooling, thread management, sessions, security, JNDI
  • Modern Trend: Embedded servers for cloud-native, microservices applications