diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java index d6c60a4cd26c51..f0d47eaceec7eb 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java @@ -29,6 +29,7 @@ import io.quarkus.smallrye.health.runtime.SmallRyeLivenessHandler; import io.quarkus.smallrye.health.runtime.SmallRyeReadinessHandler; import io.quarkus.vertx.http.deployment.RouteBuildItem; +import io.quarkus.vertx.http.runtime.HandlerType; import io.smallrye.health.SmallRyeHealthReporter; class SmallRyeHealthProcessor { @@ -91,11 +92,13 @@ void build(SmallRyeHealthRecorder recorder, RecorderContext recorderContext, feature.produce(new FeatureBuildItem(FeatureBuildItem.SMALLRYE_HEALTH)); // Register the health handler - routes.produce(new RouteBuildItem(health.rootPath, new SmallRyeHealthHandler())); + routes.produce(new RouteBuildItem(health.rootPath, new SmallRyeHealthHandler(), HandlerType.BLOCKING)); routes.produce( - new RouteBuildItem(health.rootPath + health.livenessPath, new SmallRyeLivenessHandler())); + new RouteBuildItem(health.rootPath + health.livenessPath, new SmallRyeLivenessHandler(), + HandlerType.BLOCKING)); routes.produce( - new RouteBuildItem(health.rootPath + health.readinessPath, new SmallRyeReadinessHandler())); + new RouteBuildItem(health.rootPath + health.readinessPath, new SmallRyeReadinessHandler(), + HandlerType.BLOCKING)); // Make ArC discover the beans marked with the @Health qualifier beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(HEALTH)); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java new file mode 100644 index 00000000000000..0e4c0b182d9cef --- /dev/null +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java @@ -0,0 +1,70 @@ +package io.quarkus.smallrye.health.test; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; + +import javax.enterprise.context.ApplicationScoped; + +import org.eclipse.microprofile.health.HealthCheck; +import org.eclipse.microprofile.health.HealthCheckResponse; +import org.eclipse.microprofile.health.Liveness; +import org.eclipse.microprofile.health.Readiness; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class DispatchedThreadTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(LivenessHealthCheckCapturingThread.class, ReadinessHealthCheckCapturingThread.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); + + @Test + public void check() { + RestAssured.when().get("/health/live").then() + .body("status", is("UP"), + "checks.status", contains("UP"), + "checks.name", contains("my-liveness-check"), + "checks.data.thread[0]", stringContainsInOrder("worker"), + "checks.data.thread[0]", not(stringContainsInOrder("loop"))); + + RestAssured.when().get("/health/ready").then() + .body("status", is("UP"), + "checks.status", contains("UP"), + "checks.name", contains("my-readiness-check"), + "checks.data.thread[0]", stringContainsInOrder("worker"), + "checks.data.thread[0]", not(stringContainsInOrder("loop"))); + } + + @ApplicationScoped + @Liveness + public static class LivenessHealthCheckCapturingThread implements HealthCheck { + @Override + public HealthCheckResponse call() { + return HealthCheckResponse.named("my-liveness-check") + .up() + .withData("thread", Thread.currentThread().getName()).build(); + } + } + + @ApplicationScoped + @Readiness + public static class ReadinessHealthCheckCapturingThread implements HealthCheck { + @Override + public HealthCheckResponse call() { + return HealthCheckResponse.named("my-readiness-check") + .up() + .withData("thread", Thread.currentThread().getName()).build(); + } + } + +} diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/RequestScopeHelper.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/RequestScopeHelper.java new file mode 100644 index 00000000000000..121da151668a13 --- /dev/null +++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/RequestScopeHelper.java @@ -0,0 +1,4 @@ +package io.quarkus.smallrye.health.runtime; + +public class RequestScopeHelper { +} diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java index 2c885dfd4ff46b..14e32c7317735a 100644 --- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java +++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java @@ -2,8 +2,11 @@ import java.io.ByteArrayOutputStream; +import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.spi.CDI; +import io.quarkus.arc.Arc; +import io.quarkus.arc.InjectableContext; import io.smallrye.health.SmallRyeHealth; import io.smallrye.health.SmallRyeHealthReporter; import io.vertx.core.Handler; @@ -17,17 +20,29 @@ public class SmallRyeHealthHandler implements Handler { @Override public void handle(RoutingContext event) { - - SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); - SmallRyeHealth health = reporter.getHealth(); - HttpServerResponse resp = event.response(); - if (health.isDown()) { - resp.setStatusCode(503); + boolean activated = false; + InjectableContext context = Arc.container().getActiveContext(RequestScoped.class); + if (context == null || !context.isActive()) { + Arc.container().requestContext().activate(); + activated = true; } - resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - reporter.reportHealth(outputStream, health); - resp.end(Buffer.buffer(outputStream.toByteArray())); + try { + SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); + SmallRyeHealth health = reporter.getHealth(); + HttpServerResponse resp = event.response(); + if (health.isDown()) { + resp.setStatusCode(503); + } + resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + reporter.reportHealth(outputStream, health); + resp.end(Buffer.buffer(outputStream.toByteArray())); + } finally { + if (activated) { + Arc.container().requestContext().terminate(); + } + } } } diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java index 6b68fe3ed2206d..d214aa61678b3b 100644 --- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java +++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java @@ -18,8 +18,11 @@ import java.io.ByteArrayOutputStream; +import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.spi.CDI; +import io.quarkus.arc.Arc; +import io.quarkus.arc.InjectableContext; import io.smallrye.health.SmallRyeHealth; import io.smallrye.health.SmallRyeHealthReporter; import io.vertx.core.Handler; @@ -33,17 +36,29 @@ public class SmallRyeLivenessHandler implements Handler { @Override public void handle(RoutingContext event) { - - SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); - SmallRyeHealth health = reporter.getLiveness(); - HttpServerResponse resp = event.response(); - if (health.isDown()) { - resp.setStatusCode(503); + boolean activated = false; + InjectableContext context = Arc.container().getActiveContext(RequestScoped.class); + if (context == null || !context.isActive()) { + Arc.container().requestContext().activate(); + activated = true; } - resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - reporter.reportHealth(outputStream, health); - resp.end(Buffer.buffer(outputStream.toByteArray())); + try { + SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); + SmallRyeHealth health = reporter.getLiveness(); + HttpServerResponse resp = event.response(); + if (health.isDown()) { + resp.setStatusCode(503); + } + resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + reporter.reportHealth(outputStream, health); + resp.end(Buffer.buffer(outputStream.toByteArray())); + } finally { + if (activated) { + Arc.container().requestContext().terminate(); + } + } } } diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java index 80f7b51fe0e900..2e4b1b34e48db7 100644 --- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java +++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java @@ -18,8 +18,11 @@ import java.io.ByteArrayOutputStream; +import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.spi.CDI; +import io.quarkus.arc.Arc; +import io.quarkus.arc.InjectableContext; import io.smallrye.health.SmallRyeHealth; import io.smallrye.health.SmallRyeHealthReporter; import io.vertx.core.Handler; @@ -32,17 +35,29 @@ public class SmallRyeReadinessHandler implements Handler { @Override public void handle(RoutingContext event) { - - SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); - SmallRyeHealth health = reporter.getReadiness(); - HttpServerResponse resp = event.response(); - if (health.isDown()) { - resp.setStatusCode(503); + boolean activated = false; + InjectableContext context = Arc.container().getActiveContext(RequestScoped.class); + if (context == null || !context.isActive()) { + Arc.container().requestContext().activate(); + activated = true; } - resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - reporter.reportHealth(outputStream, health); - resp.end(Buffer.buffer(outputStream.toByteArray())); + try { + SmallRyeHealthReporter reporter = CDI.current().select(SmallRyeHealthReporter.class).get(); + SmallRyeHealth health = reporter.getReadiness(); + HttpServerResponse resp = event.response(); + if (health.isDown()) { + resp.setStatusCode(503); + } + resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + reporter.reportHealth(outputStream, health); + resp.end(Buffer.buffer(outputStream.toByteArray())); + } finally { + if (activated) { + Arc.container().requestContext().terminate(); + } + } } }