Seamless MicroProfile Health integration for GuicedEE applications using Vert.x 5 Health Checks.
Annotate your classes with standard @Liveness, @Readiness, and @Startup — health checks are discovered at startup via ClassGraph, registered with Vert.x HealthChecks, and exposed as JSON endpoints on the Vert.x Web Router automatically.
Built on Vert.x Health Checks · MicroProfile Health · Google Guice · JPMS module com.guicedee.health · Java 25+
<dependency>
<groupId>com.guicedee</groupId>
<artifactId>health</artifactId>
</dependency>Gradle (Kotlin DSL)
implementation("com.guicedee:health:2.0.0-SNAPSHOT")- MicroProfile Health annotations —
@Liveness,@Readiness,@Startup, and the legacy@Healthare all supported - Automatic discovery —
HealthPreStartupscans forHealthCheckimplementations via ClassGraph and registers them with the appropriate Vert.xHealthChecksinstance - Four dedicated endpoints — aggregated
/health, plus/health/live,/health/ready, and/health/started - Configurable paths — use
@HealthOptionson any class (or package) to override default endpoint paths - Environment variable overrides —
HEALTH_ENABLED,HEALTH_PATH,HEALTH_LIVENESS_PATH,HEALTH_READINESS_PATH,HEALTH_STARTUP_PATHoverride annotation values - Guice-managed checks — health check instances are obtained from the Guice injector, so
@Injectworks inside them - Manual registration — inject the
HealthChecksinstance and register Vert.x-native checks directly - MicroProfile SPI — custom
HealthCheckResponseProviderandHealthCheckResponseBuilderprovided out of the box - Lifecycle-aware — integrated with
IGuicePreStartup(scan),IGuicePostStartup(register), andIGuicePreDestroy(cleanup) - Timeout protection — each registered check has a 2-second timeout to prevent hanging health endpoints
Step 1 — Implement a health check with a MicroProfile annotation:
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
@Liveness
public class DatabaseLiveness implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("DatabaseLiveness")
.up()
.withData("connection", "stable")
.build();
}
}Step 2 — Bootstrap GuicedEE (health endpoints are registered automatically):
IGuiceContext.registerModuleForScanning.add("my.app");
IGuiceContext.instance();
// GET /health → aggregated status
// GET /health/live → liveness checks only
// GET /health/ready → readiness checks only
// GET /health/started → startup checks onlyNo JPMS provides declaration is needed for health check classes — they are discovered via classpath scanning. The health module itself is registered automatically.
IGuiceContext.instance()
└─ IGuicePreStartup hooks
└─ HealthPreStartup.onStartup() (sortOrder = MIN_VALUE + 60)
├─ Create 4 HealthChecks instances (health, liveness, readiness, startup)
└─ Scan for HealthCheck implementations via ClassGraph
└─ Guice injector created
└─ HealthModule.configure()
└─ bind(HealthChecks.class).toInstance(healthChecks)
└─ IGuicePostStartup hooks
└─ HealthPreStartup.postLoad()
├─ Instantiate each discovered HealthCheck via Guice
├─ Inspect @Liveness, @Readiness, @Startup annotations
├─ Register with corresponding HealthChecks instance(s)
└─ Un-annotated checks register with the aggregated instance only
└─ VertxWebServerPostStartup (from web module)
└─ HealthRouterConfigurator.builder() (sortOrder = MIN_VALUE + 60)
├─ Read @HealthOptions / env vars for paths
└─ Mount HealthCheckHandler on each endpoint
Liveness checks determine if the application is running correctly. A failing liveness check typically means the application should be restarted.
@Liveness
public class ProcessLiveness implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("ProcessLiveness")
.up()
.build();
}
}Readiness checks determine if the application is ready to receive traffic. A failing readiness check means the application should be temporarily removed from the load balancer.
@Readiness
public class ServiceReadiness implements HealthCheck {
@Override
public HealthCheckResponse call() {
boolean ready = checkExternalDependencies();
return HealthCheckResponse.named("ServiceReadiness")
.status(ready)
.build();
}
}Startup checks verify if the application has finished its initialization. Failing startup checks prevent liveness probes from running during long startup sequences.
@Startup
public class InitializerStartup implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("InitializerStartup")
.up()
.build();
}
}A HealthCheck implementation without any annotation is registered with the aggregated /health endpoint only.
public class GenericCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("GenericCheck")
.up()
.withData("version", "1.0")
.build();
}
}A check can carry more than one annotation — it will be registered with each corresponding instance and the aggregated instance:
@Liveness
@Readiness
public class CriticalServiceCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("CriticalService")
.up()
.build();
}
}Place @HealthOptions on any class or package to customize endpoints:
@HealthOptions(
enabled = true,
path = "/health",
livenessPath = "/health/live",
readinessPath = "/health/ready",
startupPath = "/health/started"
)
public class MyAppConfig {
}| Attribute | Default | Description |
|---|---|---|
enabled |
true |
Enables or disables health check endpoints |
path |
/health |
Aggregated health status endpoint |
livenessPath |
/health/live |
Liveness checks endpoint |
readinessPath |
/health/ready |
Readiness checks endpoint |
startupPath |
/health/started |
Startup checks endpoint |
Every @HealthOptions attribute can be overridden with a system property or environment variable:
| Variable | Overrides | Example |
|---|---|---|
HEALTH_ENABLED |
enabled |
false |
HEALTH_PATH |
path |
/api/health |
HEALTH_LIVENESS_PATH |
livenessPath |
/api/health/live |
HEALTH_READINESS_PATH |
readinessPath |
/api/health/ready |
HEALTH_STARTUP_PATH |
startupPath |
/api/health/started |
Environment variables take precedence over annotation values.
If you need to register health checks manually using the Vert.x API, inject the HealthChecks instance:
import io.vertx.ext.healthchecks.HealthChecks;
import io.vertx.ext.healthchecks.Status;
import com.google.inject.Inject;
public class MyService {
@Inject
public MyService(HealthChecks hc) {
hc.register("my-check", 2000, promise -> promise.complete(Status.OK()));
}
}import io.vertx.ext.healthchecks.HealthChecks;
import io.vertx.ext.healthchecks.Status;
import com.google.inject.Inject;
public class MyOtherService {
@Inject
private HealthChecks hc;
public void registerChecks() {
hc.register("my-field-check", 2000, promise ->
promise.complete(Status.OK()));
}
}The aggregated HealthChecks is what Guice binds. For direct access to the liveness, readiness, or startup instances, use the static accessors:
HealthChecks liveness = HealthPreStartup.getLivenessChecks();
HealthChecks readiness = HealthPreStartup.getReadinessChecks();
HealthChecks startup = HealthPreStartup.getStartupChecks();Health endpoints return standard Vert.x health check JSON:
{
"status": "UP",
"checks": [
{
"id": "com.example.DatabaseLiveness",
"status": "UP",
"data": {
"connection": "stable"
}
},
{
"id": "com.example.ServiceReadiness",
"status": "UP"
}
]
}| HTTP Status | Meaning |
|---|---|
200 OK |
All checks are UP |
503 Service Unavailable |
One or more checks are DOWN |
When no HealthCheck implementations are found on the classpath, four placeholder checks are registered automatically (guicedee-health, guicedee-liveness, guicedee-readiness, guicedee-startup) — all returning Status.OK — so the endpoints always respond.
com.guicedee.health
├── com.guicedee.guicedinjection (GuicedEE runtime — scanning, Guice, lifecycle)
├── com.guicedee.vertx.web (Vert.x Web — Router, route mounting)
├── io.vertx.healthcheck (Vert.x Health Checks — HealthChecks, HealthCheckHandler)
├── io.vertx.web (Vert.x Web — Router integration)
├── io.vertx.core (Vert.x core)
└── com.guicedee.modules.services.health (MicroProfile Health API — annotations, SPI)
Module name: com.guicedee.health
The module:
- exports
com.guicedee.healthandcom.guicedee.health.implementations - provides
IGuiceModulewithHealthModule - provides
IGuicePreStartupwithHealthPreStartup - provides
IGuicePostStartupwithHealthPreStartup - provides
VertxRouterConfiguratorwithHealthRouterConfigurator - provides
HealthCheckResponseProviderwithGuicedHealthCheckResponseProvider
| Class | Role |
|---|---|
HealthOptions |
Annotation — configures endpoint paths and enable/disable |
HealthPreStartup |
IGuicePreStartup + IGuicePostStartup + IGuicePreDestroy — scans, registers, and manages health check lifecycle |
HealthModule |
IGuiceModule — binds the HealthChecks instance into Guice |
HealthRouterConfigurator |
VertxRouterConfigurator — mounts HealthCheckHandler on the Vert.x Router |
GuicedHealthCheckResponseProvider |
MicroProfile HealthCheckResponseProvider SPI — creates response builders |
Issues and pull requests are welcome — please add tests for new health check integrations.