Agent Skills: GuicedEE Web

Bootstrap reactive HTTP/HTTPS servers with Vert.x 5 inside GuicedEE: Router setup, BodyHandler configuration, TLS/HTTPS, SPI extension points (VertxRouterConfigurator, VertxHttpServerOptionsConfigurator, VertxHttpServerConfigurator), per-verticle sub-routers, and environment-driven configuration. Use when setting up the Vert.x web server, configuring HTTP/HTTPS, adding custom routes or middleware, or managing server options.

UncategorizedID: GuicedEE/ai-rules/guicedee-web

Install this agent skill to your local

pnpm dlx add-skill https://github.com/GuicedEE/ai-rules/tree/HEAD/skills/.system/guicedee-web

Skill Files

Browse the full folder contents for guicedee-web.

Download Skill

Loading file tree…

skills/.system/guicedee-web/SKILL.md

Skill Metadata

Name
guicedee-web
Description
"Configure GuicedEE Vert.x HTTP/HTTPS servers, routers, middleware, TLS, and server configurator SPIs."

GuicedEE Web

Reactive HTTP/HTTPS server bootstrap for GuicedEE applications using Vert.x 5.

Core Concept

Provides the Router, HttpServer, and BodyHandler plumbing that higher-level modules (rest, websockets, etc.) build on top of. Configuration is environment-driven; extension is SPI-driven. The server starts automatically via IGuicePostStartup.

Required Flow

  1. Add com.guicedee:web dependency.
  2. Bootstrap GuicedEE — the web server starts automatically:
    IGuiceContext.registerModuleForScanning.add("my.app");
    IGuiceContext.instance().inject();
    // Startup is asynchronous; await getLoadingFinished() before asserting readiness.
    
  3. 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; }
    }
    
  4. Register via JPMS:
    module my.app {
        requires com.guicedee.vertx.web;
        provides com.guicedee.vertx.web.spi.VertxRouterConfigurator
            with my.app.MyRoutes;
    }
    

SPI Extension Points

All SPIs are discovered via ServiceLoader. Register with JPMS provides...with and META-INF/services for both launch modes.

| SPI | When it runs | Purpose | |---|---|---| | VertxHttpServerOptionsConfigurator | Before servers created | Customize HttpServerOptions (ports, TLS, compression) | | VertxHttpServerConfigurator | After server creation | Configure HttpServer instance (WebSocket upgrade, connection hooks) | | VertxRouterConfigurator | After body handler | Add routes, middleware, handlers to the Router |

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 | | VERTX_MAX_BODY_SIZE | 524288000 (500 MB) | Maximum request body size |

TLS/HTTPS

Keystore format is auto-detected by file extension:

  • .jks → JKS
  • .pfx, .p12, .p8 → PKCS#12

Startup Flow

IGuiceContext.instance().inject()
 └─ IGuicePostStartup hooks
     └─ VertxWebServerPostStartup (sortOrder = MIN_VALUE + 500)
         ├─ Build HttpServerOptions (compression, keepalive, header limits)
         ├─ Apply VertxHttpServerOptionsConfigurator SPIs
         ├─ Create HTTP / HTTPS servers
         ├─ Apply VertxHttpServerConfigurator SPIs
         ├─ Create Router + BodyHandler
         ├─ Apply VertxRouterConfigurator SPIs (sorted)
         ├─ Mount per-verticle sub-routers
         ├─ Configure Jackson ObjectMapper via IJsonRepresentation
         └─ server.listen()

Isolated management listeners

Use ManagedHttpListenerProvider.listeners() for additional lifecycle-owned listeners, such as an internal health or management port. Return a list of ManagedHttpListener(name, options, vertx -> router) records and dual-register the provider in module-info.java and META-INF/services/com.guicedee.vertx.web.spi.ManagedHttpListenerProvider.

ManagedHttpListenerGroup deliberately creates a dedicated small Vert.x runtime to isolate its socket registry from the public server. It validates unique names and fixed ports, disables address/port reuse, rejects WebSocket upgrades, rolls back partially bound listeners on failure, and closes its runtime on shutdown. Build each router using the supplied Vert.x instance. Global router/server configurators are deliberately not applied; configure the listener's own routes and access policy explicitly.

ManagedHttpListenersLifecycle starts at MIN_VALUE + 800 and awaits binding. Executable mains can use GuiceApplication.run(...) from inject to await overall startup; embedded callers must observe getLoadingFinished() themselves.

WebSocket upgrade and slow-peer shutdown

Preserve WebSocketBackpressure.capture(request) at the server's request-handler handoff to the configured router. Capture happens before Vert.x Web applies forwarded-header wrappers; routing a plain request can lose the underlying transport needed for bounded shutdown.

WebSocketBackpressure.close supports raw ServerWebSocket and captured route upgrades. With Vert.x 5.2, the normal close timeout starts after the close frame flushes. A peer that stops reading can block that flush, so the helper separately schedules Netty transport closure after two seconds. Transport closure must trigger idempotent connection and subscription cleanup.

The integration uses exported Vert.x io.vertx.core.internal.http interfaces and direct io.netty.transport/io.netty.common module dependencies. It requires neither reflective wrapper inspection nor JVM --add-exports flags. Captured transport lookup uses header-object identity, avoiding collisions from reused WebSocket keys, and is removed when the channel closes. Recheck these version-specific interfaces when upgrading Vert.x.

Exercise both the direct server handler and public router upgrade with a real peer that stops reading. A successful close-handshake unit test does not prove this deadline.

Non-Negotiable Constraints

  • Public HTTP uses VertxWebServerPostStartup; additional isolated listeners use ManagedHttpListenerProvider. Isolated tests may explicitly create and close their own servers.
  • Module must requires com.guicedee.vertx.web;.
  • SPI implementations must be dual-registered (module-info.java + META-INF/services/).
  • VertxRouterConfigurator implementations control ordering via sortOrder().