Jetty

Language: Java

Web / HTTP Server

Jetty was created to offer a flexible and embeddable Java web server for developers. Unlike traditional servlet containers, Jetty can be embedded directly into applications, giving developers control over server lifecycle, configuration, and deployment. It is widely used in microservices, frameworks, and standalone Java applications requiring HTTP capabilities.

Jetty is a lightweight, high-performance Java HTTP server and servlet container. It provides an embedded web server, making it easy to integrate into Java applications for serving web content, REST APIs, or acting as a backend server.

Installation

maven: Add dependency in pom.xml: <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>11.0.20</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>11.0.20</version> </dependency>
gradle: implementation 'org.eclipse.jetty:jetty-server:11.0.20' implementation 'org.eclipse.jetty:jetty-servlet:11.0.20'

Usage

Jetty allows you to create embedded HTTP servers, deploy servlets, handle REST APIs, and manage asynchronous requests. It is suitable for both standalone applications and integration with frameworks like Spring or Jersey.

Starting a simple embedded Jetty server

import org.eclipse.jetty.server.Server;

Server server = new Server(8080);
server.start();
server.join();

Creates and starts a Jetty server listening on port 8080.

Adding a servlet

import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);

context.addServlet(new ServletHolder(new HttpServlet() {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        resp.getWriter().println("Hello from Jetty!");
    }
}), "/hello");

Registers a simple servlet that responds with 'Hello from Jetty!' to GET requests on `/hello`.

Handling asynchronous requests

context.addServlet(new ServletHolder(new HttpServlet() {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        AsyncContext async = req.startAsync();
        async.start(() -> {
            try {
                Thread.sleep(1000);
                resp.getWriter().println("Async response");
                async.complete();
            } catch(Exception e) { e.printStackTrace(); }
        });
    }
}), "/async");

Demonstrates handling asynchronous HTTP requests to improve scalability.

Deploying REST API with Jetty + Jersey

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

ResourceConfig config = new ResourceConfig().packages("com.example.resources");
ServletHolder jerseyServlet = new ServletHolder(new ServletContainer(config));
context.addServlet(jerseyServlet, "/api/*");

Integrates Jetty with Jersey to serve RESTful APIs.

Setting HTTPS

import org.eclipse.jetty.util.ssl.SslContextFactory;

SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("keystore.jks");
sslContextFactory.setKeyStorePassword("password");
ServerConnector sslConnector = new ServerConnector(server, sslContextFactory);
sslConnector.setPort(8443);
server.addConnector(sslConnector);

Configures Jetty to serve HTTPS requests using a keystore.

Error Handling

BindException: Address already in use: Ensure the configured port is free or change to another port before starting the server.
ServletException: Occurs when servlet initialization or processing fails. Check servlet code and mappings.

Best Practices

Use embedded Jetty for microservices and standalone applications for better control.

Handle exceptions within servlets to avoid server crashes.

Use thread pools and async requests to handle high concurrency.

Keep server configuration externalized for flexibility in different environments.

Combine with frameworks like Spring Boot for easier configuration and dependency injection.