Compatibility

MicroProfile Fault Tolerance

Goblin is designed to work with Fault Tolerance, not against it, at every layer:

  • Service layer (SERVICE) — the interceptor runs at @Priority(4100), inside the SmallRye Fault Tolerance interceptor (4010), so the injected fault is what your @Retry, @CircuitBreaker, @Timeout, @Bulkhead and @Fallback annotations are supposed to absorb. A latency within the armed range exercises @Timeout/@Bulkhead; a thrown exception makes @Retry re-invoke the boundary or @Fallback answer. The first attempt uses the per-request decision; each further attempt draws level again, so at level = 100 every attempt fails (and @Fallback answers) while a lower level lets some retries recover. Only the outermost intercepted call is assaulted: a bean calling another bean never multiplies the fault.

  • HTTP layer (HTTP_IN) — endpoint-level assaults apply to the JAX-RS boundary of unprotected endpoints only; fault-tolerant resources are hit before their annotations can react, which is the wrong place to validate them. The classic workflow below remains the recommended approach for HTTP_IN.

  • Outgoing layer (HTTP_OUT) — client-side latency/exceptions simulate a downstream service failing, the usual trigger for @Retry/@Fallback on data-source calls.

The classic HTTP-level workflow:

  1. Configure chaos on unprotected endpoints (default behavior).

  2. Exclude fault-tolerant endpoints via quarkus.goblin.target.exclude-annotations.

  3. Verify that the unprotected endpoints fail as expected.

  4. Remove the exclusion and arm the SERVICE (or DATABASE) layer to confirm @Timeout and @Fallback trigger correctly: at the HTTP_IN layer the fault would hit the endpoint before its annotations can react.

To exercise the resilience chain end-to-end today, arm the SERVICE layer and switch the HTTP_IN / HTTP_OUT layers off: the fault is then injected directly on the business bean and propagates through the fault-tolerance machinery, while the HTTP_IN filter stands down. A bean method excluded by quarkus.goblin.target.exclude-annotations is not woven, so keep the Fault Tolerance annotations out of that property for this workflow. The service decision is bound to the request thread: @Asynchronous methods and ManagedExecutor tasks are not covered yet, and for a method returning Uni / CompletionStage only the synchronous part of the call is. On a Vert.x event-loop thread the latency assaults that would block are skipped (a WARN is logged once) rather than blocking the loop; only the WebClient latency, which uses a Vert.x timer, still applies there.

Agroal / Hibernate ORM / Panache

The DATABASE layer is an Agroal pool interceptor, installed on every JDBC datasource when quarkus-agroal is present (which Hibernate ORM and Panache use). It is not registered in production builds, and applications without a datasource never load the Agroal API. Hibernate Reactive and the reactive SQL clients are not covered.

Quarkus Messaging

The MESSAGING layer is a CDI interceptor woven on @Incoming consumer methods when quarkus-messaging is present, whatever the connector (Kafka, AMQP, in-memory…​). It relies on no messaging API at runtime. Only the synchronous part of a consumer is covered, and latency requires a blocking consumer. Outgoing messages (Emitter, @Outgoing) are not assaulted.

Quarkus REST (RESTEasy Reactive)

Goblin uses standard JAX-RS ContainerRequestFilter / ContainerResponseFilter and targets Quarkus REST (quarkus-rest, formerly RESTEasy Reactive), which the extension is built and tested against. The classic RESTEasy runtime (quarkus-resteasy) is not tested and not supported.

MicroProfile REST Client / Quarkus REST Client

Client-side assaults are implemented as a standard JAX-RS ClientRequestFilter registered as a global provider. They apply to any client built with quarkus-rest-client (the RESTEasy Reactive-based MicroProfile REST Client implementation). The filter is inert in production builds and, being opt-in, off by default, so it has no effect unless you enable the client-side toggles.

Vert.x WebClient

The same client-side assaults apply to outgoing io.vertx.ext.web.client.WebClient calls, but Vert.x 4.x exposes no public interceptor hook on WebClient. Goblin therefore attaches its interceptor explicitly, at the point where the application creates its client, via GoblinWebClient.enable(webClient). The interceptor relies on Vert.x’s internal WebClientInternal.addInterceptor mechanism (the same one used by Vert.x’s own OAuth2WebClient, CachingWebClient and WebClientSession decorators), so it works with any client backed by Vert.x’s default WebClientImpl; a custom decorator that does not extend the base client fails fast with an IllegalArgumentException. A plain WebClient is protected by Goblin’s opt-in default: without enable(…​) it is never touched.

WebClientInternal, HttpContext and ClientPhase live in io.vertx.ext.web.client.impl and carry no compatibility guarantee. They are the only way to intercept a Vert.x 4 WebClient today; GoblinWebClientTest pins the behaviour, so a Vert.x upgrade that changes them fails the build rather than silently disabling the assaults. The integration will move to a public API when Vert.x provides one.

Micrometer / Prometheus

Observability is opt-in through the quarkus-goblin-metrics module (see Metrics (Micrometer / Prometheus)). It depends on quarkus-micrometer (API only) and registers the assault metrics against the application’s MeterRegistry: add the registry of your choice (e.g. quarkus-micrometer-registry-prometheus for /q/metrics). It co-exists with any other Micrometer-based monitoring and is inert when absent from the classpath.

OpenTelemetry

The quarkus-goblin-opentelemetry module (see Tracing (OpenTelemetry)) emits one goblin.assault span per assault through the same observer SPI, without touching the engine. It brings in quarkus-opentelemetry and reuses whatever exporter your application already configures, so the assault spans appear in your existing tracing backend; both optional modules can be present at the same time and neither interferes with the other.