API Summary

This chapter lists the whole API surface, each entry pointing at the chapter that describes it.

Every published package is @NullMarked with JSpecify, so a parameter or return value excludes null unless its signature says @Nullable. Tools that read JSpecify, such as NullAway and IntelliJ IDEA, report a null that reaches a non-null parameter.

What App provides

  • Routes: get, post, put, patch, delete, head, options, each also as (path, description, handler), and path(prefix, group → …​); patterns and matching order in Routing

  • Introspection: routes() reports every registered route as Route(method, path, description), in registration order. hooks() reports the filters and status pages beside them as Hook.BeforeRequest(path), Hook.BeforeRoute(path), Hook.AfterRoute(path), Hook.StatusPage(status), and Hook.EveryResponse(). spider-silk-openapi turns the route list into an OpenAPI 3.1 document

  • Filters: beforeRequest(filter) / beforeRequest(path, filter) before routing, beforeRoute(filter) / beforeRoute(path, filter), same for afterRoute, and responseFilter(filter) for every response, the ones no after-filter sees included

  • Logging: requestLogger((request, completion) → …​), with the servlet status, elapsed time, response definition, transmission failure, and the exception the request was answered for in RequestCompletion; see Request Logging

  • Errors: exception(Type, handler), where the most specific registered type wins and an HttpException reaches only a handler for its own type or a subtype, statusPage(HttpStatus, handler)

  • Response-wide concerns: cors(Cors), gzip() / gzip(Gzip), securityHeaders() / securityHeaders(SecurityHeaders). Each is off until called, and applies to every answer including static files and errors, which is why they are not filters; see CORS, Compression, and Security

  • Body limits: bodyLimits(BodyLimits), where BodyLimits.defaults() holds 1MB for body() and 1MB for one bodyNdjson line, and BodyLimits.unlimited() lifts both. The defaults apply without the call, and a body over a limit answers 413; see The Request

  • Rendering and assets: templates(renderer), staticFiles(classpathRoot), staticFiles(StaticFiles…​). jte over classpath:/jte and classpath:/public at the root are the defaults, so neither has to be called. StaticFiles.classpath(root) serves a classpath root and StaticFiles.directory(path) a directory on disk, several roots given at once are read in order, and precompressed() answers with a .br or .gz sibling where a build left one. FreeMarkerTemplates, HandlebarsTemplates, and ThymeleafTemplates are TemplateRenderer implementations in modules of their own

  • Server: start() / start(port), stop(), join(), port(), server(factory). Registration closes while an AppServlet serves the application, however it was started: a route, filter, or setting added then throws IllegalStateException, and stop() opens it again. Cors, Gzip, SecurityHeaders, StaticFiles, and BodyLimits are copied when they are registered

What WebRequest provides

  • Request info: method(), path(), header(name), headers(name) for a repeated header, headers() for all of them, contentType(), queryString(), isSecure(), scheme(), host(), remoteAddress(), and raw() for the servlet request itself. host() carries the port when it is not the scheme’s default, so scheme(), host(), and path() rebuild the absolute URL

  • The matched route: route(), the Route that answered, with its pattern and description; null before routing and where no route matched, see Route Introspection

  • Path variables: pathParam, pathParamLong, pathParamEnum, and pathParam(name, parser) for any other type. A name the pattern never declared throws IllegalStateException, not a 400. A \{name*} tail binds the rest of the path with its slashes, and "" when it matched nothing

  • Parameters: param (400 when missing), paramOrNull (null when missing), paramLong, paramBoolean (true or false only), paramEnum, each with a (…​, default) form for optional parameters; params(name) for repeated values

  • Any other type: param(name, parser) and param(name, parser, default), where the parser is a Function<String, T> such as UUID::fromString or LocalDate::parse. A parser that throws IllegalArgumentException or DateTimeException answers 400 naming the parameter

  • One source only: queryParam(name) and formParam(name) require a value and answer 400 when absent. queryParamOrNull(name) and formParamOrNull(name) return null when absent. The parser overloads require a value too, unless the (…​, parser, default) form supplies a default

  • Query vs. form: queryParam, queryParams, formParam, formParams

  • Content negotiation: accepts(types…​) answers with the type the caller prefers out of the ones offered, 406 when it will take none of them; acceptedTypes() for the parsed Accept header

  • Cookies the client sent: cookie(name), cookies()

  • Body: body(), bodyJson(), bodyJson(reader) (400 on a body the reader rejects, 413 on a body over the limit). The bytes are read once and kept, so every call answers the whole body, and bodyJson parses them as they arrived

  • Multipart uploads: file(name) (400 when absent), fileOrNull(name) (null when absent), files(name) for a field that carries several, and 413 or 400 from all three for an upload the container refuses. UploadedFile answers fileName(), contentType(), size(), bytes(), text(), inputStream(), and writeTo(path)

  • Body, unread: bodyStream() and bodyReader() hand it over for a parser from another library, and neither mixes with the kept text: whichever goes second throws IllegalStateException. bodyNdjson(reader) reads newline-delimited JSON lazily, and answers 400 naming the line, or 413 for a line over the limit; see Large JSON and NDJSON and External JSON Binding

  • Session: session() answers a WebSession, where get(key, Class<T>) reads under a named type and fails on that line naming the key and both types, get(key) leaves the cast to the call site, set(key, value) writes, remove(key) removes one, and invalidate() ends the session

  • Flash: flash(key, value), read exactly once with flashed(key) on the request after a redirect, and a null value removes the key as it does for a session attribute

  • Errors: errorMessage() inside a statusPage(status, handler) handler

What WebResponse provides

  • Bodies: html, text, rawJson(text), json(JsonValue), json(value, writer), bytes(contentType, data), template(name), template(name, model), stream(contentType, out → …​), file(path), sse(stream → …​), raw((req, res) → …​)

  • Model.of(…​) builds the immutable Model that template(name, model) takes, of up to ten entries that may hold null values; see Templates

  • model.with(key, value) answers a model with one more entry, and model.asMap() answers a read-only map for a renderer

  • A jte template called through a method that jte-models generates is sent with html(templates.deck(deck).render()); see Templates

  • file(path) reads the content type from the name and the length from the file. A path that is not a readable regular file throws UncheckedIOException, so a 404 for a missing file is the handler’s line to write

  • Bodies written a value at a time: jsonArray(sink → …​) for an array too big to hold, and ndjson(sink → …​) for one value per line. Both are a stream body underneath, and the writer runs outside handler exception handling. The sink is a JsonSink, whose write(value) and write(value, writer) each write one value; see Large JSON and NDJSON

  • Statuses: empty(), empty(HttpStatus), noContent(), redirect(location), redirect(location, HttpStatus)

  • Building on: status, header, withoutHeader(name), contentType, vary(field), attachment, body, cookie(name, value), cookie(name, value, maxAge), cookie(Cookie), expireCookie

  • Reading back: status(), header(name), headers(), cookies(), body(). Header names compare without regard to case, and one field holds one value however many spellings set it. A header that must be sent twice is written through raw; see Headers

See The Response for the shape of body() and the lambda families.

What net.benelog.silkjson provides

The package belongs to silk-json, the JSON library core is built on.

  • The tree: Json.object(), Json.array(), Json.parse(text), Json.parse(utf8), and JsonValue with JsonObject, JsonArray, and JsonPrimitive; see JSON

  • Mappings: JsonWriter<T>, a lambda (value, out) → …​ over a JsonOutput; JsonReader<T>, a lambda over a JsonInput; and JsonCodec<T>, both at once. JsonWriter.list, JsonWriter.tree, JsonReader.object, JsonReader.list, JsonReader.tree, JsonCodec.of, and JsonCodec.list build them. writer.toJson(value), writer.toJsonBytes(value), reader.fromJson(text), and reader.fromJsonBytes(utf8) run one outside a request

  • JsonOutput: object(), array(), end(), name(key), put(key, …​), putNull(key), value(…​), nullValue(), values(strings), and newline(). JsonOutput.inMemory() answers toBytes() and toJson(), or length() and writeTo(stream) followed by release(), and JsonOutput.to(stream) sends its buffer on flush()

  • JsonInput: object(), array(), nextKey(), nextKeyIs(key), keyHead(), nextElement(), keyIs(key), key(), readString(), readLong(), readInt(), readDouble(), readFloat(), readNumber(), readOneOf(names), readBoolean(), readNull(), readValue(), readValueBytes(), skipValue(), end(), and error(message), over JsonInput.of(utf8) or JsonInput.of(text)

  • JsonKey.of(name): a member name encoded once, for put, name, and keyIs

  • JsonKey.names(constants): an enum’s constant names encoded once, for put(key, name), value(name), and readOneOf

  • @JsonBound: the codec of the annotated type, or of the type it names, generated at compile time as <Type>Json.CODEC by silk-json-processor; see Generated JSON Codecs