Skip to content

Latest commit

 

History

64 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GuicedEE Vert.x Web

Build Maven Central License

Java 25+ Guice 7 Vert.X 5

Reactive HTTP/HTTPS server bootstrap for GuicedEE applications using Vert.x 5. Provides the RouterConfig, HttpServer, and BodyHandler plumbing that higher-level modules (rest, websockets, etc.) build on top of. Configuration is environment-driven; extension is SPI-driven.

Built on Vert.x Web · GuicedEE · JPMS module com.guicedee.vertx.web · Java 25+

📦 Installation

<dependency>
  <groupId>com.guicedee</groupId>
  <artifactId>web</artifactId>
</dependency>
Gradle (Kotlin DSL)
implementation("com.guicedee:web:2.2.0")

✨ Features

  • Auto-start HTTP/HTTPS serversVertxWebServerPostStartup runs as an IGuicePostStartup hook and creates servers from environment config
  • Three SPI extension pointsVertxHttpServerOptionsConfigurator, VertxHttpServerConfigurator, VertxRouterConfigurator
  • TLS/HTTPS — JKS and PKCS#12 keystores auto-detected by file extension
  • Body handlingBodyHandler pre-configured with file uploads, form merging, and configurable size limits
  • Per-verticle sub-routersVertxWebVerticleStartup creates isolated routers for @Verticle-annotated packages
  • Jackson integrationDatabindCodec mapper configured via IJsonRepresentation at startup
  • Environment-driven — HTTP/HTTPS ports, TLS, body limits all controlled via system properties or environment variables

🚀 Quick Start

Bootstrap GuicedEE — the web server starts automatically via the post-startup hook:

IGuiceContext.registerModuleForScanning.add("my.app");
IGuiceContext.instance();
// HTTP server is now listening on port 8080 (default)

Add routes by implementing VertxRouterConfigurator:

public class MyRoutes implements VertxRouterConfigurator<MyRoutes> {

    @Override
    public Router builder(Router router) {
        router.get("/health").handler(ctx ->
            ctx.response().end("OK"));
        return router;
    }

    @Override
    public Integer sortOrder() {
        return 500;  // higher = later
    }
}

Register via JPMS:

module my.app {
    requires com.guicedee.vertx.web;

    provides com.guicedee.vertx.web.spi.VertxRouterConfigurator
        with my.app.MyRoutes;
}

📐 Startup Flow

flowchart TD
    n1["IGuiceContext.instance()"]
    n2["IGuicePostStartup hooks"]
    n1 --> n2
    n3["VertxWebServerPostStartup<br/>sortOrder = MIN_VALUE + 500"]
    n2 --> n3
    n4["Build HttpServerOptions<br/>compression, keepalive, header limits"]
    n3 --> n4
    n5["Apply VertxHttpServerOptionsConfigurator SPIs"]
    n3 --> n5
    n6["Create HTTP server<br/>if HTTP_ENABLED=true"]
    n3 --> n6
    n7["Create HTTPS server<br/>if HTTPS_ENABLED=true, with TLS keystore"]
    n3 --> n7
    n8["Apply VertxHttpServerConfigurator SPIs"]
    n3 --> n8
    n9["Create Router + BodyHandler"]
    n3 --> n9
    n10["Apply VertxRouterConfigurator SPIs<br/>sorted, excluding per-verticle"]
    n3 --> n10
    n11["Mount per-verticle sub-routers from VertxWebRouterRegistry"]
    n3 --> n11
    n12["Configure Jackson ObjectMapper via IJsonRepresentation"]
    n3 --> n12
    n13["Attach router to all servers"]
    n3 --> n13
    n14["server.listen() for each server"]
    n3 --> n14
Loading

🔌 SPI Extension Points

All SPIs are discovered via ServiceLoader. Register implementations with JPMS provides...with or META-INF/services.

VertxHttpServerOptionsConfigurator

Customize HttpServerOptions before servers are created — ports, TLS, compression, buffer sizes:

public class MyServerOptions implements VertxHttpServerOptionsConfigurator {
    @Override
    public HttpServerOptions builder(HttpServerOptions options) {
        options.setIdleTimeout(60);
        return options;
    }
}

VertxHttpServerConfigurator

Configure the HttpServer instance after creation — WebSocket upgrade handlers, connection hooks:

public class MyServerConfig implements VertxHttpServerConfigurator {
    @Override
    public HttpServer builder(HttpServer server) {
        server.connectionHandler(conn ->
            log.info("New connection from {}", conn.remoteAddress()));
        return server;
    }
}

VertxRouterConfigurator

Add routes, middleware, and handlers to the RouterConfig. Implements IDefaultService so sortOrder() controls execution order:

public class StaticFiles implements VertxRouterConfigurator<StaticFiles> {
    @Override
    public Router builder(Router router) {
        router.route("/static/*").handler(StaticHandler.create("webroot"));
        return router;
    }

    @Override
    public Integer sortOrder() {
        return 900;  // run after REST routes
    }
}

⚙️ Configuration

All configuration is driven by system properties or environment variables:

Variable Default Purpose
HTTP_ENABLED true Enable HTTP server
HTTP_PORT 8080 HTTP listen port
HTTPS_ENABLED false Enable HTTPS server
HTTPS_PORT 443 HTTPS listen port
HTTPS_KEYSTORE Path to JKS or PKCS#12 keystore
HTTPS_KEYSTORE_PASSWORD Keystore password (changeit default for JKS)
VERTX_MAX_BODY_SIZE 524288000 (500 MB) Maximum request body size in bytes

HTTPS / TLS

Keystore format is auto-detected by file extension:

Extension Format
.jks JKS
.pfx, .p12, .p8 PKCS#12
# Generate a self-signed JKS keystore for development
keytool -genkey -alias dev -keyalg RSA -keysize 2048 \
  -validity 365 -keystore keystore.jks -storepass changeit

Default server options

VertxWebServerPostStartup applies these defaults before any SPI configurator runs:

Option Value
Compression enabled, level 9
TCP keep-alive true
Max header size 65 536 bytes
Max chunk size 65 536 bytes
Max form attribute size 65 536 bytes
Max form fields unlimited (-1)
Max initial line length 65 536 bytes

Body handler defaults

A BodyHandler is installed on all routes with:

Setting Value
Uploads directory uploads
Delete uploaded files on end true
Handle file uploads true
Merge form attributes true
Body limit VERTX_MAX_BODY_SIZE (default 500 MB)

🔀 Per-Verticle Sub-Routers

When a package is annotated with @Verticle, VertxWebVerticleStartup creates a dedicated RouterConfig for that package's VertxRouterConfigurator implementations. These sub-routers are mounted onto the main router automatically.

This means route configurators in @Verticle packages are excluded from the global router and instead run inside their verticle's isolated context.

@Verticle(workerPoolName = "api-pool", workerPoolSize = 8)
package com.example.api;

Any VertxRouterConfigurator in com.example.api (or sub-packages) will be applied to a dedicated sub-router mounted by VertxWebVerticleStartup.

🗺️ Module Graph

flowchart LR
    com_guicedee_vertx_web["com.guicedee.vertx.web"]
    com_guicedee_vertx_web --> com_guicedee_vertx["com.guicedee.vertx<br/>Vert.x lifecycle, event bus, verticles"]
    com_guicedee_vertx_web --> io_vertx_web["io.vertx.web<br/>Vert.x Web — Router, BodyHandler, etc."]
    com_guicedee_vertx_web --> io_vertx_core["io.vertx.core<br/>Vert.x core — HttpServer, HttpServerOptions"]
    com_guicedee_vertx_web --> com_guicedee_client["com.guicedee.client<br/>GuicedEE SPI contracts"]
Loading

🧩 JPMS

Module name: com.guicedee.vertx.web

The module:

  • exports com.guicedee.vertx.web.spi
  • provides IGuicePostStartup with VertxWebServerPostStartup
  • uses VertxRouterConfigurator, VertxHttpServerConfigurator, VertxHttpServerOptionsConfigurator

🏗️ Key Classes

Class Role
VertxWebServerPostStartup IGuicePostStartup — builds servers, router, and starts listening
VertxWebVerticleStartup VerticleStartup — creates per-verticle sub-routers
VertxWebRouterRegistry Thread-safe registry for sub-routers contributed by verticles
VertxRouterConfigurator SPI — add routes and handlers to the RouterConfig
VertxHttpServerConfigurator SPI — customize HttpServer instances
VertxHttpServerOptionsConfigurator SPI — customize HttpServerOptions before server creation

🤝 Contributing

Issues and pull requests are welcome — please add tests for new SPI implementations or server configurations.

📄 License

Apache 2.0

Additional isolated HTTP listeners

Implement com.guicedee.vertx.web.spi.ManagedHttpListenerProvider and return ManagedHttpListener definitions (name, defensive-copy HttpServerOptions, and Function<Vertx, Router>). Register the provider in both module-info.java (provides ... with ...) and the matching META-INF/services file. Return an empty list to disable the feature without allocating another runtime.

The lifecycle loads providers through Guice after normal web initialization, awaits every bind, rolls back this group's listeners on failure and closes them on shutdown, including a bind still in progress. Applications must propagate startup-hook failure to their launcher; this hook does not stop unrelated servers.

Build each router using the supplied Vert.x instance. The group owns a separate non-clustered runtime with one event-loop thread, one worker and one internal blocking worker. It does not install the application's router/server configurators, body parser, routes, authentication, metrics instrumentation or event-bus bridge. Existing thread-safe application health/metrics services can be used by handlers; providers are responsible for access policy, bounded non-blocking work and TLS. The runtime closes with the group and is not created when there are no listeners.

This separation prevents Vert.x from silently sharing a public socket on address collision. Socket reuse is forced off; names and positive ports must be unique within the group. Port zero requests distinct ephemeral bindings; negative shared ports are rejected. All direct WebSocket upgrades are denied. An occupied socket fails startup instead of dispatching a private router on another server's port.

ManagedHttpListenerTest exercises real loopback HTTP, bind failure and rollback, public socket collision, duplicate ports, shutdown races and copied options.

About

A Vertx Web Configuration module

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages