Repository navigation
Releases
1.0.0
Added
Modules - 2026-10-19
veredium-core: the stack-neutral part both client modules share - the mesh timeout ladder
(app.mesh,eu.inqudium.veredium.core.mesh), the breaker verdicts (benign 4xx is a success, a
client-side failure is ignored) and the Resilience4j wiring that installs them (one
*ConfigCustomizerper mesh alias, the fail-fast startup guard, the ladder logger). Each client
contributes only its exception vocabulary (RestClientVerdicts,WebClientVerdicts), which its
auto-configuration hands to the core's wiring through its ownMeshResilienceRegistrarsubclass. ADR-0001; resolves finding 1 of the
origin module's architecture review (tool-box, 2026-10-19).veredium-restclient: the blocking client - SpringRestClientover Apache HttpClient 5, one
resilience-wrapped client per mesh endpoint, the timeout ladder derived from one measured anchor,
the Resilience4j verdicts and rungs installed through the library's customizers with a fail-fast
startup guard, a bounded body read and legatium's exchange event. Ported from dhaase/tool-box.veredium-webclient: the reactive sibling - SpringWebClientover Reactor Netty with the same
mesh ladder, the same Resilience4j customizer wiring and legatium's exchange event. Ported from
dhaase/tool-box.
Both client stacks in one host - 2026-10-23
- Both client modules in one host (ADR-0003):
app.mesh.endpoints[].stack(restclient/webclient) assigns an
endpoint to the stack that serves it. Needed only when a host depends on both modules - with one, every endpoint
belongs to it. Each stack's customizers, startup guard and factory cover its own endpoints only; a factory refuses
the other stack's endpoint, and an engine override for it, naming the owner.MeshOwnershipCheckfails the start,
before any registry or pool exists, for an endpoint both stacks or no stack would serve.veredium-exampleshas a
mixed example with both clients in one context.
HTTP engines - 2026-10-21 to 2026-10-23
-
Selectable HTTP engine per client stack, with a per-backend override (
engine.endpoints.<mesh-alias>):veredium-restclient:app.restclient.engine.defaulttakesapache(default),jdk,jettyor
reactor-netty.veredium-webclient:app.webclient.engine.defaulttakesreactor-netty(default),jdk,jettyor
apache.
The setting applies to the module's own clients only. Boot's global
spring.http.clients.*switches are
neither read nor written, and no transport bean is registered. Boot'sRestClient.Builder/WebClient.Builder
bean is left untouched, because the engine is set on the module's clone of it. No process-global resource or
system property is used. Isolation tests pin all of this against Boot's real HTTP-client auto-configuration.Each engine is created with the factory, shared by the backends that select it, and released on shutdown. The mesh
ladder is mapped onto every engine as far as it allows. What an engine cannot apply, for example pool size
and pending-acquire on the JDK client, is stated in a startup line and in the module guides, not silently
ignored.The non-default engine libraries are optional dependencies:
jetty-clientandreactor-netty-httpfor the
blocking client;jetty-client/jetty-reactive-httpclientandhttpclient5/httpcore5-reactivefor the
reactive one.The start fails, naming the key:
- for an override key that is not a mesh alias,
- for an engine whose library is missing (with its Maven coordinates),
- for
jdkwhile the JDK would replace the backend'sHostheader. The host enables that header itself
with-Djdk.httpclient.allowRestrictedHeaders=host.
Cancellation (TimeLimiter expiry, interrupted caller, cancelled future or subscription) abandons the
exchange on every engine. For Jetty and Reactor Netty on the blocking side, and for Apache on the reactive
side, this closes gaps in Spring Framework 7.0.9's adapters.
Examples - 2026-10-24
veredium-examples: the decorator example shows the MDC hand-off.CorrelatedCustomerLookupputs a request id in
the caller's MDC, and the adapter's line on the decorator's worker carries it, fordecorateanddecorateAsync
alike. A fan-out over threads of the host's own hands the caller's MDC on withCallerMdc.with, because the
decorator copies the MDC of the thread that calls it.
Build and project setup - 2026-10-19 to 2026-10-23
- A new build-only module,
veredium-examples, shows a host using both clients: one Spring Boot
application per calling style - blocking and asynchronous on the RestClient, reactive on the WebClient - each
with an adapter over two backends and the configuration it needs, and one that bounds a native Apache HttpClient 4
call with the core'sBlockingResilienceDecorator. Its tests start each
application against a WireMock stand-in for the sidecar, so an example that stops working fails the build. Like
veredium-coverageandveredium-test-supportit is never published; all three have a README that says why
each is a module of its own. - A new build-only module,
veredium-test-support, holds the test helpers both client modules
share - the raw-socket backends, the thread-safe log capture,eventually, the WireMock arrival listener, the
configuration-file binding, the test payloads and the customized registries - in place of the copies that had
drifted apart in each module. Likeveredium-coverageit is never published. - The
veredium-coremodule, the build (Maven, Kotlin, Spring Boot parent,
JaCoCo, ktlint, Dokka, CycloneDX, reproducible jars), the CI, CodeQL, Scorecard, Docs, Fuzz
and Release workflows, and the documentation site - set up from the sibling project
Legatium.
Fixed
Most entries resolve the findings of the defect analyses in docs/assessment/
(DEFECT_ANALYSIS-2026-10-21T20-14-02.md, -2026-10-22T14-01-49.md, -2026-10-23T05-20-01.md,
-2026-10-24T10-08-59.md, -2026-10-24T19-38-36.md).
Shutdown and engine release - 2026-10-22 to 2026-10-24
-
veredium-webclient: on the Reactor Netty engine, a shutdown thread that was interrupted no longer fails the
engine's release. Its wait for the pool's disposal was ablock(), which answers an interrupt with an exception:
the event loops were never scheduled for disposal and outlived the context, calls in flight ran until their
response timeout, and the log showed "failed to release its resources" with a stack trace. The wait now ends on
the interrupt with the shared drain line ("because the shutdown thread was interrupted"), keeps the flag, and the
loops go in any case. The interrupted-shutdown case now runs on every reactive engine. -
veredium-webclient: the Reactor Netty engine's drain line names the drain window, as every engine's does,
instead of the part of the shared deadline that was left when its turn came. -
veredium-restclient: on the Reactor Netty engine, a head wait that finished just as the worker was interrupted
has its response closed, instead of holding its pooled connection. -
veredium-restclient: on the Reactor Netty engine, a call still waiting for its response head when a shutdown
past its deadline disposed the event loops could hang until its TimeLimiter budget. Spring's wait for the head
is ablock()without a time bound, and the response timeout is a timer on those loops. Seen once on CI; not
reproduced locally. The wait now runs on the engine's hand-off executor, like each body read already did, and
the shutdown'sshutdownNowof that executor ends it at once with anIOException. A unit test pins the
hand-off. -
veredium-webclient: the Apache engine's release no longer fails a call that is still waiting for a
connection. It shut the I/O reactor down at once, and a reactor inSHUTTING_DOWNopens no connection, so a
call queued behindmax-connectionsfailed with anIOReactorShutdownExceptionas soon as the connection it
waited for came free, although the drain deadline left it all the time it needed. The release now waits for
the engine's exchanges in flight first, as Jetty's does, and shuts the reactor down after. A per-engine test
of a call waiting for a connection pins it; on Apache it failed after 0.6 s of a 5 s deadline before the fix.
The "in-flight exchange finishes" case, before on Jetty only, now runs on every reactive engine. -
veredium-webclient: the Reactor Netty engine's release no longer fails a call that is still waiting for a
connection either. Its pool was disposed without adisposeTimeout, which is no graceful shutdown: pending
acquires failed at once with aPoolShutdownException. The pool is now built with the factory's drain bound as
itsdisposeTimeout, so its disposal serves the waiting calls and completes once every connection came back;
the release now waits for in-flight calls on every reactive engine alike. -
veredium-webclient: the JDK and Apache engines' release WARN names an interrupted shutdown thread as the
reason, as Jetty's and the blocking module's do. -
veredium-restclient: the factory's shutdown releases every engine even when one of them throws, reporting
the failure in a WARN line; a Reactor Netty disposal past its wait is reported instead of thrown out of the
destroy callback; a Jetty client stopped from an interrupted shutdown thread no longer blocks the shutdown.
Engines created before one that fails to construct are shut down before the failure is rethrown. -
veredium-restclient:create()aftershutdown()is refused with anIllegalStateExceptioninstead of
building a client on a closed engine. -
veredium-restclient: the Apache pool's gauges (restclient.pool.*) leave the host's registry on shutdown,
as Reactor Netty's do. -
veredium-webclient:shutdown()releases all e...