diff --git a/docs/src/main/asciidoc/_admin-guide/subsystem-configuration/MicroProfile_Health.adoc b/docs/src/main/asciidoc/_admin-guide/subsystem-configuration/MicroProfile_Health.adoc
index e7f8c36dd688..d9493c3a4207 100644
--- a/docs/src/main/asciidoc/_admin-guide/subsystem-configuration/MicroProfile_Health.adoc
+++ b/docs/src/main/asciidoc/_admin-guide/subsystem-configuration/MicroProfile_Health.adoc
@@ -19,18 +19,45 @@ element to the xml or by using the following CLI operation:
[standalone@localhost:9990 /]/extension=org.wildfly.extension.microprofile.health-smallrye:add
----
-== Management Operation
+== Management Operations
+
+The healthiness of the application server can be queried by calling 3 different operations:
+
+* `check` to check both the liveness and readiness of the runtime
+* `check-live` to check only the liveness of the runtime
+* `check-ready` to check only the readiness of the runtime
-The healthiness of the application server can be queried by calling the `check`:
[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=microprofile-health-smallrye:check
{
- "outcome" => "success", <1>
+ "outcome" => "success",
"result" => {
- "outcome" => "UP", <2>
- "checks" => []
+ "status" => "UP",
+ "checks" => [
+ {
+ "name" => "empty-liveness-checks",
+ "status" => "UP"
+ },
+ {
+ "name" => "server-state",
+ "status" => "UP",
+ "data" => {"value" => "running"}
+ },
+ {
+ "name" => "boot-errors",
+ "status" => "UP"
+ },
+ {
+ "name" => "deployments-status",
+ "status" => "UP"
+ },
+ {
+ "name" => "empty-readiness-checks",
+ "status" => "UP"
+ }
+ ]
}
}
----
@@ -40,6 +67,7 @@ The healthiness of the application server can be queried by calling the `check`:
== HTTP Endpoints
The MicroProfile Health Check specifications defines three HTTP endpoints:
+
* `/health` to test both the liveness and readiness of the runtime.
* `/health/live` to test the liveness of the runtime.
* `/health/ready` to test the readiness of the runtime.
@@ -58,7 +86,7 @@ If the application server is healthy, it will return a `200 OK` response:
$ curl -v http://localhost:9990/health
< HTTP/1.1 200 OK
...
-{"outcome":"UP","checks":[]}
+{"status":"UP","checks":[{"name":"empty-liveness-checks","status":"UP"},{"name":"server-state","status":"UP","data":{"value":"running"}},{"name":"boot-errors","status":"UP"},{"name":"deployments-status","status":"UP"},{"name":"empty-readiness-checks","status":"UP"}]}
----
If the application server (and its deployment) is not healthy, it returns `503 Service Unavailable`
@@ -79,28 +107,28 @@ created by the `add-user` script. For example:
$ curl -v --digest -u myadminuser:myadminpassword http://localhost:9990/health
< HTTP/1.1 200 OK
...
-{"outcome":"UP","checks":[]}
+{"status":"UP","checks":[{"name":"empty-liveness-checks","status":"UP"},{"name":"server-state","status":"UP","data":{"value":"running"}},{"name":"boot-errors","status":"UP"},{"name":"deployments-status","status":"UP"},{"name":"empty-readiness-checks","status":"UP"}]}
----
If the authentication fails, the server will reply with a `401 NOT AUTHORIZED` response.
-=== Global Status when probes are not defined
+=== Default Server Procedures
+
+WildFly provides some readiness procedures that are checked to determine if the application server is ready to serve requests:
-By default, the HTTP endpoints will return `UP` if there are no health check probes defined by the application.
+* `boot-errors` checks that there were no errors during the server boot sequence
+* `deployments-status` checks that all deployments were deployed without errors
+* `server-state` checks that the server state is `running`
+* `empty-readiness-checks` determines the status when there are no deployments on the server. The outcome of this procedure is determined by the `empty-readiness-checks-status` attribute. If the attribute is
+ `UP` (by default), the server can be ready when there are no readiness checks in the deployments. Setting the `empty-readiness-checks-status` attribute to `DOWN` will make this procedure fail when there are no readiness checks in the deployments.
-However, it is possible to change this behaviour.
-The `/health/live` HTTP endpoint (as well as the `check-live` management operation) can return `DOWN` when there are no liveness check probes by setting the `empty-liveness-checks-status` attribute
-on the `subsystem` resource to `DOWN`.
-Similarly, the `/health/ready` HTTP endpoint (as well as the `check-ready` management operation) can return `DOWN` when there are no readiness check probes by setting the `empty-readiness-checks-status` attribute
-on the `subsystem` resource to `DOWN`.
+WildFly also provide a liveness procedure that is checked to determine if the application server is live:
-This allows application to ensure that the HTTP liveness and readiness endpoints will return `DOWN` until their probes are deployed and used to determine the actual
-liveness and readiness state of the application.
+* `empty-liveness-checks` determines the status when there are no deployments on the server. The outcome of this procedure is determined by the `empty-liveness-checks-status` attribute. If the attribute is
+`UP` (by default), the server can be live when there are no liveness checks in the deployments. Setting the `empty-liveness-checks-status` attribute to `DOWN` will make this procedure fail when there are no liveness checks in the deployments.
-[NOTE]
-There is a specific behaviour for deployments that provides no _readiness_ probes. In that the case, WildFly automatically adds a readiness probe for the deployment that always return
-`UP`. This allows existing deployments that do not provide readiness probes to configure WildFly so it will not be ready until this deployment is actually deployed.
+It is possible to disable all these server procedures by using the MicroProfile Config property `mp.health.disable-default-procedures`.
== Component Reference
diff --git a/microprofile/health-smallrye/pom.xml b/microprofile/health-smallrye/pom.xml
index a5ee6dd72dde..65f9d486ffec 100644
--- a/microprofile/health-smallrye/pom.xml
+++ b/microprofile/health-smallrye/pom.xml
@@ -64,6 +64,10 @@
+
+ org.wildfly.core
+ wildfly-controller-client
+
org.wildfly.core
wildfly-server
@@ -129,11 +133,6 @@
vdx-wildfly
test
-
- org.wildfly.core
- wildfly-controller-client
- test
-
org.wildfly.core
wildfly-subsystem-test
diff --git a/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporter.java b/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporter.java
index 802ce39b6592..673d2c72419f 100644
--- a/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporter.java
+++ b/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporter.java
@@ -22,6 +22,7 @@
package org.wildfly.extension.microprofile.health;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -42,48 +43,87 @@ public class HealthReporter {
public static final String DOWN = "DOWN";
public static final String UP = "UP";
+ private final boolean defaultServerProceduresDisabled;
private Map healthChecks = new HashMap<>();
private Map livenessChecks = new HashMap<>();
private Map readinessChecks = new HashMap<>();
+ private Map serverReadinessChecks = new HashMap<>();
- private final String emptyLivenessChecksStatus;
- private final String emptyReadinessChecksStatus;
+ private final HealthCheck emptyDeploymentLivenessCheck;
+ private final HealthCheck emptyDeploymentReadinessCheck;
- public HealthReporter(String emptyLivenessChecksStatus, String emptyReadinessChecksStatus) {
- this.emptyLivenessChecksStatus = emptyLivenessChecksStatus;
- this.emptyReadinessChecksStatus = emptyReadinessChecksStatus;
+ private static class EmptyDeploymentCheckStatus implements HealthCheck {
+ private final String name;
+ private final String status;
+
+ EmptyDeploymentCheckStatus(String name, String status) {
+ this.name = name;
+ this.status = status;
+ }
+
+ @Override
+ public HealthCheckResponse call() {
+ return HealthCheckResponse.named(name)
+ .state(status.equals("UP"))
+ .build();
+ }
+ }
+
+
+ public HealthReporter(String emptyLivenessChecksStatus, String emptyReadinessChecksStatus, boolean defaultServerProceduresDisabled) {
+ this.emptyDeploymentLivenessCheck = new EmptyDeploymentCheckStatus("empty-liveness-checks", emptyLivenessChecksStatus);
+ this.emptyDeploymentReadinessCheck = new EmptyDeploymentCheckStatus("empty-readiness-checks", emptyReadinessChecksStatus);
+ this.defaultServerProceduresDisabled = defaultServerProceduresDisabled;
}
public SmallRyeHealth getHealth() {
- String emptyChecksStatus = DOWN.equals(emptyLivenessChecksStatus) || DOWN.equals(emptyReadinessChecksStatus) ? DOWN : UP;
- return getHealth(emptyChecksStatus, healthChecks, livenessChecks, readinessChecks);
+ HashMap deploymentChecks = new HashMap<>();
+ deploymentChecks.putAll(healthChecks);
+ deploymentChecks.putAll(livenessChecks);
+ deploymentChecks.putAll(readinessChecks);
+
+ HashMap serverChecks= new HashMap<>();
+ serverChecks.putAll(serverReadinessChecks);
+ if (deploymentChecks.size() == 0 && !defaultServerProceduresDisabled) {
+ serverChecks.put(emptyDeploymentLivenessCheck, Thread.currentThread().getContextClassLoader());
+ serverChecks.put(emptyDeploymentReadinessCheck, Thread.currentThread().getContextClassLoader());
+ }
+
+ return getHealth(serverChecks, deploymentChecks);
}
public SmallRyeHealth getLiveness() {
- return getHealth(emptyLivenessChecksStatus, livenessChecks);
+ final Map serverChecks;
+ if (livenessChecks.size() == 0 && !defaultServerProceduresDisabled) {
+ serverChecks = Collections.singletonMap(emptyDeploymentLivenessCheck, Thread.currentThread().getContextClassLoader());
+ } else {
+ serverChecks = Collections.emptyMap();
+ }
+ return getHealth(serverChecks, livenessChecks);
}
public SmallRyeHealth getReadiness() {
- return getHealth(emptyReadinessChecksStatus, readinessChecks);
+ final Map serverChecks = new HashMap<>();
+ serverChecks.putAll(serverReadinessChecks);
+ if (readinessChecks.size() == 0 && !defaultServerProceduresDisabled) {
+ serverChecks.put(emptyDeploymentReadinessCheck, Thread.currentThread().getContextClassLoader());
+ }
+ return getHealth(serverChecks, readinessChecks);
}
-
- @SafeVarargs
- private final SmallRyeHealth getHealth(String emptyChecksStatus, Map... checks) {
+ private final SmallRyeHealth getHealth(Map serverChecks, Map deploymentChecks) {
JsonArrayBuilder results = Json.createArrayBuilder();
HealthCheckResponse.State status = HealthCheckResponse.State.UP;
- if (checks != null) {
- for (Map entry : checks) {
- status = processChecks(entry, results, status);
- }
- }
+ status = processChecks(serverChecks, results, status);
+
+ status = processChecks(deploymentChecks, results, status);
JsonObjectBuilder builder = Json.createObjectBuilder();
JsonArray checkResults = results.build();
- builder.add("status", checkResults.isEmpty() ? emptyChecksStatus : status.toString());
+ builder.add("status", status.toString());
builder.add("checks", checkResults);
return new SmallRyeHealth(builder.build());
@@ -171,6 +211,12 @@ public void addReadinessCheck(HealthCheck check, ClassLoader moduleClassLoader)
}
}
+ public void addServerReadinessCheck(HealthCheck check, ClassLoader moduleClassLoader) {
+ if (check != null) {
+ serverReadinessChecks.put(check, moduleClassLoader);
+ }
+ }
+
public void removeReadinessCheck(HealthCheck check) {
readinessChecks.remove(check);
}
diff --git a/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporterService.java b/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporterService.java
index 26d294311f99..98f26baa3efe 100644
--- a/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporterService.java
+++ b/microprofile/health-smallrye/src/main/java/org/wildfly/extension/microprofile/health/HealthReporterService.java
@@ -31,6 +31,7 @@
import io.smallrye.health.ResponseProvider;
import io.smallrye.health.SmallRyeHealthReporter;
+import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.jboss.as.controller.CapabilityServiceBuilder;
import org.jboss.as.controller.LocalModelControllerClient;
@@ -80,21 +81,25 @@ private HealthReporterService(Supplier modelContro
@Override
public void start(StartContext context) {
- healthReporter = new HealthReporter(emptyLivenessChecksStatus, emptyReadinessChecksStatus);
+ // MicroProfile Health supports the mp.health.disable-default-procedures to let users disable any vendor procedures
+ final boolean defaultServerProceduresDisabled = ConfigProvider.getConfig().getOptionalValue("mp.health.disable-default-procedures", Boolean.class).orElse(false);
+ healthReporter = new HealthReporter(emptyLivenessChecksStatus, emptyReadinessChecksStatus, defaultServerProceduresDisabled);
modelControllerClient = modelControllerClientFactory.get().createClient(managementExecutor.get());
- healthReporter.addReadinessCheck(new ServerStateCheck(modelControllerClient));
- healthReporter.addReadinessCheck(new NoBootErrorsCheck(modelControllerClient));
- healthReporter.addReadinessCheck(new DeploymentsStatusCheck(modelControllerClient));
+ if (!defaultServerProceduresDisabled) {
+ healthReporter.addServerReadinessCheck(new ServerStateCheck(modelControllerClient), Thread.currentThread().getContextClassLoader());
+ healthReporter.addServerReadinessCheck(new NoBootErrorsCheck(modelControllerClient), Thread.currentThread().getContextClassLoader());
+ healthReporter.addServerReadinessCheck(new DeploymentsStatusCheck(modelControllerClient), Thread.currentThread().getContextClassLoader());
+ }
HealthCheckResponse.setResponseProvider(new ResponseProvider());
}
@Override
public void stop(StopContext context) {
- this.modelControllerClient.close();
- this.healthReporter = null;
+ modelControllerClient.close();
+ healthReporter = null;
HealthCheckResponse.setResponseProvider(null);
}
diff --git a/microprofile/health-smallrye/src/main/resources/org/wildfly/extension/microprofile/health/LocalDescriptions.properties b/microprofile/health-smallrye/src/main/resources/org/wildfly/extension/microprofile/health/LocalDescriptions.properties
index f89f07ea4324..55caaaffa290 100644
--- a/microprofile/health-smallrye/src/main/resources/org/wildfly/extension/microprofile/health/LocalDescriptions.properties
+++ b/microprofile/health-smallrye/src/main/resources/org/wildfly/extension/microprofile/health/LocalDescriptions.properties
@@ -5,5 +5,5 @@ microprofile-health-smallrye.check=Check both the liveness and readiness of the
microprofile-health-smallrye.check-live=Check the liveness of the application server and its deployments
microprofile-health-smallrye.check-ready=Check the readiness of the application server and its deployments
microprofile-health-smallrye.security-enabled=True if authentication is required to access the HTTP endpoints on the HTTP management interface.
-microprofile-health-smallrye.empty-liveness-checks-status=Defines the global status returned by the Health checks endpoints if no liveness probes have been defined.
-microprofile-health-smallrye.empty-readiness-checks-status=Defines the global status returned by the Health checks endpoints if no readiness probes have been defined.
\ No newline at end of file
+microprofile-health-smallrye.empty-liveness-checks-status=Defines the global status returned by the Health checks endpoints if no liveness probes have been defined in deployments.
+microprofile-health-smallrye.empty-readiness-checks-status=Defines the global status returned by the Health checks endpoints if no readiness probes have been defined in deployments.
\ No newline at end of file
diff --git a/microprofile/health-smallrye/src/test/java/org/wildfly/extension/microprofile/health/Subsystem_2_0_ParsingTestCase.java b/microprofile/health-smallrye/src/test/java/org/wildfly/extension/microprofile/health/Subsystem_2_0_ParsingTestCase.java
index 99c38a9bc795..dd9935b0d558 100644
--- a/microprofile/health-smallrye/src/test/java/org/wildfly/extension/microprofile/health/Subsystem_2_0_ParsingTestCase.java
+++ b/microprofile/health-smallrye/src/test/java/org/wildfly/extension/microprofile/health/Subsystem_2_0_ParsingTestCase.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import static org.wildfly.extension.microprofile.health.MicroProfileHealthExtension.VERSION_1_0_0;
import static org.wildfly.extension.microprofile.health.MicroProfileHealthSubsystemDefinition.HTTP_EXTENSIBILITY_CAPABILITY;
+import static org.wildfly.extension.microprofile.health.MicroProfileHealthSubsystemDefinition.MANAGEMENT_EXECUTOR;
import java.io.IOException;
import java.util.List;
@@ -110,7 +111,8 @@ private static String getMicroProfileSmallryeHeatlhGAV(ModelTestControllerVersio
protected AdditionalInitialization createAdditionalInitialization() {
return AdditionalInitialization.withCapabilities(
HTTP_EXTENSIBILITY_CAPABILITY,
- WELD_CAPABILITY_NAME);
+ WELD_CAPABILITY_NAME,
+ MANAGEMENT_EXECUTOR);
}
private void testRejectingTransformers(ModelTestControllerVersion controllerVersion, ModelVersion healthVersion) throws Exception {
diff --git a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadyHTTPEndpointTestCase.java b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadyHTTPEndpointTestCase.java
index 243376d4bd85..6279e1d87fdd 100644
--- a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadyHTTPEndpointTestCase.java
+++ b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadyHTTPEndpointTestCase.java
@@ -55,11 +55,12 @@ void checkGlobalOutcome(ManagementClient managementClient, String operation, boo
try (CloseableHttpClient client = HttpClients.createDefault()) {
CloseableHttpResponse resp = client.execute(new HttpGet(healthURL));
- assertEquals(mustBeUP ? 200 : 503, resp.getStatusLine().getStatusCode());
-
String content = EntityUtils.toString(resp.getEntity());
resp.close();
+ assertEquals(content, mustBeUP ? 200 : 503, resp.getStatusLine().getStatusCode());
+
+
try (
JsonReader jsonReader = Json.createReader(new StringReader(content))
) {
diff --git a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadySetupTask.java b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadySetupTask.java
index c9fe0a970b74..984f698d2369 100644
--- a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadySetupTask.java
+++ b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationReadySetupTask.java
@@ -34,7 +34,7 @@ public class MicroProfileHealthApplicationReadySetupTask implements ServerSetupT
public void setup(ManagementClient managementClient, String containerId) throws Exception {
final ModelNode address = Operations.createAddress("subsystem", "microprofile-health-smallrye");
final ModelNode op = Operations.createWriteAttributeOperation(address, "empty-readiness-checks-status", "DOWN" );
- ModelNode result = managementClient.getControllerClient().execute(op);
+ managementClient.getControllerClient().execute(op);
ServerReload.reloadIfRequired(managementClient);
}
diff --git a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWitouhtReadinessHTTPEndpointTestCase.java b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWithoutReadinessHTTPEndpointTestCase.java
similarity index 98%
rename from testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWitouhtReadinessHTTPEndpointTestCase.java
rename to testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWithoutReadinessHTTPEndpointTestCase.java
index abd848a8738f..624f0be7909e 100644
--- a/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWitouhtReadinessHTTPEndpointTestCase.java
+++ b/testsuite/integration/basic/src/test/java/org/wildfly/test/integration/microprofile/health/MicroProfileHealthApplicationWithoutReadinessHTTPEndpointTestCase.java
@@ -43,7 +43,7 @@
/**
* @author Jeff Mesnil (c) 2019 Red Hat inc.
*/
-public class MicroProfileHealthApplicationWitouhtReadinessHTTPEndpointTestCase extends MicroProfileHealthApplicationWithoutReadinessTestBase {
+public class MicroProfileHealthApplicationWithoutReadinessHTTPEndpointTestCase extends MicroProfileHealthApplicationWithoutReadinessTestBase {
void checkGlobalOutcome(ManagementClient managementClient, String operation, boolean mustBeUP, String probeName) throws IOException {
diff --git a/testsuite/integration/microprofile-tck/health/src/test/resources/arquillian.xml b/testsuite/integration/microprofile-tck/health/src/test/resources/arquillian.xml
index aa741fa6aaab..d9ca0703b875 100644
--- a/testsuite/integration/microprofile-tck/health/src/test/resources/arquillian.xml
+++ b/testsuite/integration/microprofile-tck/health/src/test/resources/arquillian.xml
@@ -5,7 +5,7 @@
${jboss.home}
- ${microprofile.jvm.args}
+ ${microprofile.jvm.args} -Dmp.health.disable-default-procedures=true
${jboss.server.config.file.name:standalone-microprofile.xml}
127.0.0.1
9990