Skip to main content

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 /healthz
  • GET /readyz
  • GET /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) via HealthProbeConfiguration.

A third flavor, HealthResource, mounts the same three probes as a routed child (@Rest(children=HealthResource.class)) under a parent's /health subtree — 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 OK when no component is DOWN.
  • 503 Service Unavailable when any component is DOWN.

Quick start​

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.LIVE
  • HealthProbe.READY
  • HealthProbe.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();
}