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.- One
HttpContextis registered per spec binding atspec.basePath()(the firstservers[].urlpath from the OpenAPI doc). Unless a binding owns/, a catch-all/context serves extra routes viaExtrasRouterand 404s everything else;ExceptionFilterwraps that context only. - On a binding context, two filters run in order, then the handler:
RequestPreparationFilter— reads the request body throughRequestBodyReader(which decodes a registeredContent-Encoding— gzip is built in — under a size cap), resolves the route, runs OpenAPI parameter + body validation viaDefaultValidator, and binds the resultingRequestinto theDispatchHandler.CURRENTscoped value. It renders its own failures through theExceptionHandlerrather than relying onExceptionFilter.SecurityFilter— enforces the spec'ssecuritySchemes/security, re-binding theRequestwith resolved principals. It writes its 401/403 responses straight to the exchange.DispatchHandler— looks up theRequestHandlerregistered for the resolvedoperationIdin the user-supplied map and invokes it, applying interceptors and response decorators. Handler coverage is verified at boot, so the lookup never returnsnull.
Every response except SecurityFilter's rejections is written by ResponseRenderer, which is also where response content coding is applied.
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 9457application/problem+json400 responses.com.retailsvc.http.internal.Router— two indexes: exact path map and templated path list. ResolvesoperationId+ extracted path variables for each request.TypeMapper— per-media-type request parsing and response writing; registered viaBuilder.bodyMapper(...), withGsonTypeMapperauto-registered when Gson is on the classpath.com.retailsvc.http.Request— an immutable record-like carrier built from primitives (body bytes, path parameters, raw query string, a header lookup function), never theHttpExchange.bytes()returns the decoded body,parsed()the object produced by theTypeMapper.com.retailsvc.http.ContentCoding— a pluggable HTTP content coding. gzip is built in (internal/GzipCoding); callers register others on the builder, held per direction ininternal/ContentCodings.RequestBodyReaderdecodes requests under the size cap andResponseRenderercodes responses. See the README's "Content encoding" section for the policy.
- 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.