BoxExpress is an Express.js-style web framework for BoxLang, running on Undertow with a virtual thread per request — no servlet container needed. It covers routing, middleware, sessions, views, file serving, WebSockets, a full STOMP broker, and a scheduler. New: cross-process cluster support, with leader-elected scheduled jobs and STOMP pub/sub relayed across instances, backed by a durable shared cache. Real example apps: bxThreads (forum) and bx-graphql-demo.
Tag
boxlang
20 articles
Ported my forum app (DismalThreads) from ColdBox/CBWIRE to BoxLang/boxlang-express as bxThreads — swapping CBWIRE's component reactivity for hand-rolled fetch()/websockets. Porting a real app with existing opinions (auth, rate limiting, realtime fan-out) is a better BoxLang stress test than starting fresh, since a blank project lets you dodge every hard problem by never hitting it.
BoxExpress adds server-sent events and full WebSocket support for pushing live updates to clients — dashboards, progress bars, chat, notifications. Built from scratch, since BoxExpress skips BoxLang's built-in web layer. Along the way: a concurrency bug in broadcast connections, a header-injection-style hole in SSE metadata, a BoxLang update that broke page rendering, and a STOMP bug letting one client hijack another's subscription. All caught by trying to break it.
bx-graphql brings GraphQL to native BoxLang via graphql-java, wrapping it in a schema-agnostic module with convention-based resolvers and zero framework lock-in. To prove it out beyond source code, Robert built a fully offline demo pairing it with boxlang-express — a JSONPlaceholder-style schema, thin resolvers that mostly fall through to `PropertyDataFetcher`, and a no-build-step query console. Both modules are live on ForgeBox: `box install` and go.
BoxExpress 0.1.15→0.2.1: five patch releases fixed empty-value crashes (query/cookie/multipart), hardened proxy-IP trust for real platforms, fixed session data loss against non-memory stores, added response outcome accessors and opt-out session writes, and closed a trailing-slash bug hitting nearly every request. Then 0.2.0 replaced the JDK's HttpServer with Undertow entirely (breaking), verified at full parity and load-tested. 0.2.1 added live HTTP-layer metrics via getConnectorStatistics().
Robert replaced a synchronous third-party analytics service (which caused outages when rate-limited) with a custom `RequestLogger.bx` for his site. It uses a bounded in-memory queue, non-blocking middleware, and a background scheduled thread to batch-flush rows to SQL every 5s, with periodic cleanup of old records. Doubles as a boxlang-express middleware tutorial covering closures, Java interop (ConcurrentLinkedQueue, dynamic proxies), and defensive error handling.
This site runs on one 1-vCPU DigitalOcean instance with no APM vendor — just a self-built page reading JVM metrics directly, and the habit of watching it. Covers which numbers actually matter (GC time ÷ uptime, not raw seconds), a real bug caught along the way (the JVM thought it had 8 cores, not 1), load-testing to find the real throughput ceiling, and trimming the Docker image 60% by dropping CommandBox entirely.
I rebuilt this blog on boxlang-express, my own Express.js-style BoxLang framework, moving from a CommandBox droplet to a thin DigitalOcean App container, with static assets on Cloudflare R2 and a homegrown MySQL access log replacing GoatCounter. Also: DismalThreads, my BoxLang/CBWire Reddit-style forum, is getting decommissioned end of month, no real users beyond my own test accounts, though the code may go public on GitHub.
BoxLang Express went from basic routing to a full-featured framework across 10 releases (0.1.1→0.1.14): sessions, CSRF, CORS, rate limiting, security headers, uploads, and a SQL-backed session store. Every fix got verified live before being called done, then locked in as one of 149 passing tests. Along the way, express-test grew from a chat demo into a live documentation site, catching stale docs and gotchas that reading alone would've missed.
BoxExpress brings Express.js-style HTTP endpoints to BoxLang using the JDK's built-in HTTP server. It supports routing, middleware, sub-routers, static files, and view rendering—without requiring a servlet container.
Robert built a Slack clone on BoxLang with no bundler, no database, no auth. Channels are free because addresses are free. Presence isn't stored, it's derived. DMs are channels with computed names. Two bugs taught me more than the features: frames aren't ordered, and `content-length` counts bytes.
Robert rebuilt his 8-year-old Vue D&D combat app in BoxLang, using SocketBox/WebSockets for real-time state. Features SRD 5.2 character creation, turn-based combat with fog-of-war, and a chunked map system with dual-layer tiles and POI markers. Encounter state lives server-side; ~300 TestBox tests cover it.