Validation
Luxis exposes two validation entry points:
validate(v -> ...)— available on every stream type (HTTP, WebSocket, event). Validates the inbound payload viav.field(...)andv.listField(...).validateHttp(v -> ...)— available only onHttpStream(HTTP handlers and filters). Addsv.queryParam(...)andv.pathParam(...)on top of the base field rules.
Both evaluate all rules in a block together and short-circuit with a 422 response if any fail.
Pipeline Position
Section titled “Pipeline Position”validateHttp() is only available on HttpStream — the stream type you receive at the start of an HTTP handler or filter. As soon as you call any transformation step (map, flatMap, blockingMap, blockingFlatMap, asyncMap, …), the stream type widens to LuxisStream and validateHttp() is no longer accessible. The base validate() still works after transformations, but it cannot reach query or path parameters because it has no HttpSession.
In practice this means HTTP-aware validation must run before any other pipeline step. You may chain multiple validateHttp() calls together, and you may combine them with requireJwt(), but once you transform the request you can no longer use validateHttp().
// OK — validateHttp() is the first stepreturn e .validateHttp(v -> { v.field("name", r -> r.name).required().minLength(2); v.field("email", r -> r.email).required().email(); }) .map(ctx -> buildUser(ctx.in())) .complete(ctx -> HttpResult.success(ctx.in()));// Also OK — validateHttp() after requireJwt() (both live on HttpStream)return e .requireJwt(jwtProvider) .validateHttp(v -> v.field("name", r -> r.name).required()) .map(ctx -> buildUser(ctx.in())) .complete(ctx -> HttpResult.success(ctx.in()));// Does not compile — once you map, the stream is no longer an HttpStreamreturn e .map(ctx -> ctx.in()) .validateHttp(v -> v.field("name", r -> r.name).required()) // compile error .complete(ctx -> HttpResult.success(ctx.in()));Basic Validation
Section titled “Basic Validation”Inside a validateHttp() block, use field() for body fields, queryParam() for query string parameters, and pathParam() for path parameters:
.validateHttp(v -> { v.field("name", r -> r.name).required().minLength(2); v.field("email", r -> r.email).required().email(); v.field("age", r -> r.age).required().min(0).max(150); v.queryParam("page").required().matches("[0-9]+"); v.pathParam("userId").required().matches("[0-9]+");})The base validate() block has the same shape but exposes only field() and listField() — there is no HttpSession available, so query and path parameters cannot be validated through it.
Nested Objects
Section titled “Nested Objects”Nested objects use a field overload that takes a validation block for the nested type. The block is only evaluated when the nested value is non-null, and error keys are prefixed with the parent field name:
v.field("address", r -> r.address, a -> { a.field("city", x -> x.city).required(); a.field("zip", x -> x.zip).required().matches("[0-9]{5}");});Lists are validated with listField, which supports size constraints and per-element validation via each():
v.listField("addresses", r -> r.addresses) .required() .minSize(1) .maxSize(10) .each(a -> { a.field("city", x -> x.city).required(); a.field("zip", x -> x.zip).required().matches("[0-9]{5}"); });Element errors are keyed by index, e.g. addresses[0].city.
Error Response Format
Section titled “Error Response Format”On failure the response status is 422 Unprocessable Entity and the body is:
{ "message": "Validation failed", "errors": { "name": ["must not be blank"], "email": ["must be a valid email address"], "address.zip": ["must match pattern: [0-9]{5}"] }}Available Rules
Section titled “Available Rules”String Rules
Section titled “String Rules”| Rule | Description |
|---|---|
required() | Must not be null or blank |
minLength(n) | Minimum string length |
maxLength(n) | Maximum string length |
email() | Must be a valid email address |
matches(regex) | Must match the given regex pattern |
Numeric Rules
Section titled “Numeric Rules”| Rule | Description |
|---|---|
required() | Must not be null |
min(n) | Minimum value |
max(n) | Maximum value |
List Rules
Section titled “List Rules”| Rule | Description |
|---|---|
required() | Must not be null |
minSize(n) | Minimum list size |
maxSize(n) | Maximum list size |
each(block) | Validate each element |