Health / Readiness / Liveness Probes
See also: REST Server — Mixins and Multi-Mount Paths — the underlying
@Rest(mixins=...)and@Rest(paths=...)composition primitives this page is built on.
Starting with 10.0.0, Juneau provides an opt-in probe surface for Jetty microservices:
GET /healthzGET /readyzGET /livez
Probe routing now has two supported integration styles:
- Preferred: mix probe operations into your existing root resource with
@Rest(mixins=HealthMixin.class). - Fallback: standalone probe servlet auto-mounted at explicit
@Rest(paths={...})path specs (/healthz,/readyz,/livez) viaHealthProbeConfiguration.
A third flavor,
HealthResource, mounts the same three probes as a routed child (@Rest(children=HealthResource.class)) under a parent's/healthsubtree — see REST Server — Standalone vs Mixin Resources for how the three flavors relate.
This avoids root-path collisions when your app already owns @Rest(path="/").
The endpoints aggregate every HealthIndicator bean from the microservice bean store and return an
Actuator-style payload:
{
"status": "UP",
"components": {
"dbHealth": {
"status": "UP",
"details": {
"validationQueryMs": 12
}
}
}
}
HTTP status is:
200 OKwhen no component isDOWN.503 Service Unavailablewhen any component isDOWN.
Quick start
Option A (recommended): mix into existing root resource
import org.apache.juneau.commons.inject.*;
import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
import org.apache.juneau.rest.server.*;
import org.apache.juneau.rest.server.health.*;
import org.apache.juneau.rest.server.servlet.*;
@Rest(
path="/",
mixins=HealthMixin.class
)
public class RootResources extends BasicRestServlet {
@Bean(name="dbHealth")
HealthIndicator dbHealth() {
return () -> Health.up("db").detail("validationQueryMs", 12).build();
}
}
public class App {
public static void main(String[] args) throws Exception {
Microservice.create()
.args(args)
.configurations(JettyConfiguration.class)
.build()
.start()
.join();
}
}
Each named HealthIndicator method is registered separately; @Bean methods may be package-private.
Option B: standalone auto-mount (escape hatch)
import org.apache.juneau.commons.inject.*;
import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.jetty.*;
import org.apache.juneau.rest.server.health.*;
import jakarta.servlet.*;
@Configuration
public class AppConfig {
@Bean
Servlet root() {
return new RootResources();
}
@Bean
HealthIndicator dbHealth() {
return () -> Health.up("db").detail("validationQueryMs", 12).build();
}
}
public class App {
public static void main(String[] args) throws Exception {
Microservice.create()
.args(args)
.configurations(JettyConfiguration.class, HealthProbeConfiguration.class, AppConfig.class)
.build()
.start()
.join();
}
}
HealthProbeConfiguration contributes a Servlet bean (HealthServlet) and Jetty mounts it
at the three explicit path specs declared on the resource via @Rest(paths={...}).
HealthIndicator SPI
HealthIndicator is a functional interface:
@FunctionalInterface
public interface HealthIndicator {
Health check();
}
Return values are created with Health.up(name), Health.down(name, throwable), and
Health.unknown(name), with optional .detail(key, value) entries.
Indicators can scope themselves to probe types by overriding probes() and returning a set of
HealthProbe values:
HealthProbe.LIVEHealthProbe.READYHealthProbe.STARTUP
By default, indicators participate in both liveness and readiness probes.
Timeout behavior
Each indicator runs with a timeout from HealthProbeSettings (default: 1 second). If a check times
out or throws, the component is marked DOWN and the error is surfaced in details.error.
Override defaults by contributing your own settings bean:
@Bean
HealthProbeSettings probeSettings() {
return HealthProbeSettings.create()
.timeout(Duration.ofSeconds(2))
.build();
}