Lightweight (~120KB) wrapper over the JDK's built-in HTTP server.
Features:
- Context abstraction over
HttpExchange
to easily retrieve and send request/response data. - Fluent API
- Static resource handling
- Server Sent Events
- Compression SPI
- Json SPI
- Virtual threads enabled by default
- Multi-Server with any implementation of
jdk.httpserver
(Jetty, Robaho, built-in, etc)
Add dependency:
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-jex</artifactId> <version>${jex.version}</version> </dependency>
Create Server:
Jex.create() .get("/", ctx -> ctx.text("hello")) .get("/one/{id}", ctx -> ctx.text("one-" + ctx.pathParam("id"))) .filter( (ctx, chain) -> { System.out.println("before request"); chain.proceed(); System.out.println("after request"); }) .error( IllegalStateException.class, (ctx, exception) -> ctx.status(500).text(exception.getMessage())) .port(8080) .start();
Use with Avaje Http
If you find yourself pining for the JAX-RS style of controllers, you can have avaje http generate jex adapters for your annotated classes.
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-jex</artifactId> <version>${jex.version}</version> </dependency> <dependency> <groupId>io.avaje</groupId> <artifactId>avaje-http-api</artifactId> <version>${avaje.http.version}</version> </dependency> <!-- Annotation processor --> <dependency> <groupId>io.avaje</groupId> <artifactId>avaje-http-jex-generator</artifactId> <version>${avaje.http.version}</version> <scope>provided</scope> <optional>true</optional> </dependency>
In JDK 23+, annotation processors are disabled by default, you will need to add a flag to re-enable.
<properties> <maven.compiler.proc>full</maven.compiler.proc> </properties>
package org.example.hello; import io.avaje.http.api.Controller; import io.avaje.http.api.Get; import java.util.List; @Controller("/widgets") public class WidgetController { private final HelloComponent hello; public WidgetController(HelloComponent hello) { this.hello = hello; } @Get("/{id}") Widget getById(int id) { return new Widget(id, "you got it"+ hello.hello()); } @Get() List<Widget> getAll() { return List.of(new Widget(1, "Rob"), new Widget(2, "Fi")); } record Widget(int id, String name){}; }
This will generate routing code that we can register using any JSR-330 compliant DI:
@Generated("avaje-jex-generator") @Singleton public class WidgetController$Route implements Routing.HttpService { private final WidgetController controller; public WidgetController$Route(WidgetController controller) { this.controller = controller; } @Override public void add(Routing routing) { routing.get("/widgets/{id}", this::_getById); routing.get("/widgets", this::_getAll); } private void _getById(Context ctx) throws IOException { ctx.status(200); var id = asInt(ctx.pathParam("id")); ctx.json(controller.getById(id)); } private void _getAll(Context ctx) throws IOException { ctx.status(200); ctx.json(controller.getAll()); } }
You can use whatever DI library you like.
public class Main { public static void main(String[] args ) { List<Routing.HttpService> services = // Retrieve HttpServices via DI; Jex.create().routing(services).start(); } }
The JDK provides an SPI to swap the underlying HttpServer
, so you can easily use jex with alternate implementations by adding them as a dependency.
Jetty is a classic embedded server with a long and distinguished history.
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-jex</artifactId> <version>${jex.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-http-spi</artifactId> <version>${jetty.version}</version> </dependency>
@robaho's httpserver is a zero-dependency implementation that seems to increase performance by 10x over the built-in implementation, and 5x over Jetty in certain benchmarks.
<dependency> <groupId>io.avaje</groupId> <artifactId>avaje-jex</artifactId> <version>${jex.version}</version> </dependency> <dependency> <groupId>io.github.robaho</groupId> <artifactId>httpserver</artifactId> <version>${robaho.version}</version> </dependency>
See also:
- Javalin (A lightweight wrapper over Jetty)