This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A lightweight Java 25 library that wraps the JDK's built-in com.sun.net.httpserver.HttpServer and exposes endpoints declared in an OpenAPI 3.1.x specification. Consumers register HttpHandler instances by OpenAPI operationId. The library is published as a JAR; the example launcher under src/test/java/.../start/ServerLauncher.java is for local development only.
Java 25 is required (see .java-version). The server uses thread-per-request with virtual threads.
- Build:
mvn package - Unit tests (Surefire):
mvn test - Integration tests (Failsafe,
*IT.java):mvn verify - Single test class:
mvn test -Dtest=OpenApiServerTest - Single test method:
mvn test -Dtest=OpenApiServerTest#methodName - Coverage report: produced at
target/site/jacoco/aftermvn verify - POM is sort-checked by
sortpom-maven-pluginduringvalidate; fix withmvn sortpom:sort - Pre-commit hooks (Google Java formatter, commitlint, editorconfig, etc.) run via
pre-commit; install withpre-commit install --hook-type pre-commit --hook-type commit-msg - Run example server locally:
mvn test-compile exec:java -Dexec.mainClass=com.retailsvc.http.start.ServerLauncher -Dexec.classpathScope=test(or runServerLauncherfrom the IDE). Test schema lives atsrc/test/resources/openapi.json. - Acceptance/load probes: k6 scripts under
acceptance/k6/. ZAP scan via./zap.sh.
Request flow when OpenApiServer boots (src/main/java/com/retailsvc/http/OpenApiServer.java):
HttpServeris created on a port with a virtual-thread-per-task executor.- A single
HttpContextis registered atspec.basePath()(the firstservers[].urlpath from the OpenAPI doc). A catch-all/context returns 404. - Three filters run in order on every request:
ExceptionFilter— wraps the chain; delegates uncaught exceptions to the user-suppliedExceptionHandler(default inHandlers).RequestPreparationFilter— reads the raw request body, stashes it as an exchange attribute, runs OpenAPI parameter + body validation viaDefaultValidator, and stores the resolvedoperationIdon the exchange.DispatchHandler— looks up theHttpHandlerregistered for thatoperationIdin the user-supplied map and invokes it. Handler coverage is verified at boot, so the lookup never returnsnull.
Key abstractions:
com.retailsvc.http.spec.Spec— parsed from a consumer-suppliedMap<String, Object>viaSpec.from(raw). No JSON library dependency in the library itself; callers use Gson, Jackson, SnakeYAML, etc. to produce the map.- Sealed
com.retailsvc.http.spec.schema.Schemainterface with per-kind records (StringSchema,NumberSchema,IntegerSchema,ArraySchema,ObjectSchema,BooleanSchema,NullSchema,AnyOfSchema,AllOfSchema,OneOfSchema). Pattern-match dispatch eliminates instanceof chains. com.retailsvc.http.validate.DefaultValidator— single class usingswitchpattern-match overSchemasubtypes. Validation failures produce RFC 7807application/problem+json400 responses.com.retailsvc.http.internal.Router— two indexes: exact path map and templated path list. ResolvesoperationId+ extracted path variables for each request.JsonMapper—@FunctionalInterface; single methodObject mapFrom(byte[]). Callers supply a lambda (see README).com.retailsvc.http.Request— static helper;Request.bytes(exchange)returns raw body bytes,Request.parsed(exchange)returns theObjectproduced by theJsonMapper.
- Code is formatted with the Google Java Formatter (enforced by pre-commit). Do not hand-format.
- Commit messages must satisfy commitlint (Conventional Commits).
- Integration tests are named
*IT.javaand run only undermvn verify, notmvn test. - The library has
slf4j-apiasprovided— never add a transitive logging binding to main scope.