Learn how to provide and check the health of a microservice using MicroProfile Health.
You will learn how to use Microprofile Health feature to report the health of a RESTful application. The great benefit from adding a health check is that it helps in machine to machine communications, monitoring and knowing which services are performing in the application.
A health check is a method for assessing the states of the services in an application to know the overall performance. The state of a service is either UP
or DOWN
.
When the state is UP
, the service is available. However, when it is DOWN
, the service
is currently not available (i.e. in maintenance). The overall outcome of the application is UP
only when the checks of all the services are UP
.
The MicroProfile Health feature provides an endpoint that you can get the health check results as a JSON object. This HTTP request endpoint returns a status code of 200
if the application outcome is UP
, otherwise, a status code of 503
if it is DOWN
.
You will add health checks to report the states of the PropertiesResource
and InventoryResource
RESTful services in an inventory management application. This application and the two services in it are provided for you in this guide. If you want to learn how to create a RESTful application, see
Creating a RESTful web service.
The fastest way to work through this guide is to clone the git repository and use the starting project
that is provided in the start
directory. To do this, run the following commands:
git clone https://github.com/openliberty/guide-mp-health.git cd guide-mp-health/start
The finish
directory in the root of this guide contains the finished
health check implementation for the services in the application. Feel free to give it a try before you proceed with building your own.
To try out the application, first navigate to the finish
directory and then execute the following
Maven goals to build the application and run it inside Open Liberty:
mvn install liberty:start-server
Point your browser to MicroProfile Health Check endpoint: http://localhost:9080/health
. From here, you can see the health of the two services as well as the overall health outcome of the applicaiton. As shown, there are two checks. One that shows the state of PropertiesResource
service and the other shows the state of InventoryResource
service. They are both in UP
state as you may expect and because of that the overall outcome of the application is UP
.
You can also verify states of the two RESTful services by pointing to their endpoints: - http://localhost:9080/system/properties refers to the PropertiesResource service that retrieves the information for a specific host - http://localhost:9080/inventory/hosts refers to the InventoryResource service that retrieves the information for a list of all previously registered hosts
Once you are done checking out the application, stop the Open Liberty server:
mvn liberty:stop-server
Now, navigate back to the start
directory to begin.
Begin by enabling the MicroProfile Health feature in your pom.xml
file. This feature allows you to
use the MicroProfile Health API to provide health checks to your RESTful services.
Navigate to the start/pom.xml file and add the required dependency:
link:finish/pom.xml[role=include]
Proceed with the two sections below to add health checks to PropertiesResource
and
InventoryResource
services.
Create PropertiesHealth.java
class in /start/src/main/java/io/openliberty/guides/system/
to report the health of the PropertiesResource service.
link:finish/src/main/java/io/openliberty/guides/system/PropertiesHealth.java[role=include]
The org.eclipse.microprofile
package contains the required MicroProfile Health Check classes.
The @Health
annotation indicates that this class will be read for reporting the state of
a desired service to /health
endpoint. The @ApplicationScoped
annotation is
required because the health check service must stay active within the lifetime of the application for the
state to be reported.
This class implements the HealthCheck
interface, which means you must override the call()
method from this interface.
The healthy state of the PropertiesResource
service is simulated by reading the system property of the
host. If the system property wlp.server.name
is defaultServer
, then the state is UP
, otherwise, it
is DOWN
.
Lastly, you need to pass the service name PropertiesResource
as an argument to the named()
method to indicate that this is the service being reported.
Create a class InventoryHealth.java
in /start/src/main/java/io/openliberty/guides/inventory/
to report the health of the InventoryResource service.
link:finish/src/main/java/io/openliberty/guides/inventory/InventoryHealth.java[role=include]
This service reports its healthy state depending on two conditions:
-
A property of type boolean found in
/start/CustomConfigSource.json
. This property is used this file to manipulate on the state of the service. This file is provided for you in this guide. If you want to learn how to configure this file, see Configuring Microservices using MicroProfile Config."io.openliberty.guides.microprofile.inventory.inMaintenance": false
-
PropertiesResource
service availability (i.e. returns 200 response code).
As you can see, adding health check to this service is similar as in the previous section above. However, there are minor adjustments and additions.
The @Inject
annotation is used to initialize the InventoryConfig
object. This object will allow
you to read the property in the CustomConfigSource.json
file. You can learn more about the @Inject
annotation from
Handling dependencies with RESTful web services.
The isHealthy()
method returns a boolean that determines the health of InventoryResource
service.
It checkes the two conditions that were mentioned above. This method is used as the condition in call()
method. The state of InventoryResource
service is UP
if isHealthy
returns true
and vice versa.
Now, open InventoryResource
in /start/src/main/java/io/openliberty/guides/inventory/
to add a condition to this service.
link:finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[role=include]
The service reports the system properties for a hostname through calling
getPropertiesForHost()
method. This can only happen if the io.openliberty.guides.microprofile.inventory.inMaintenance
configuration is set to false
. Otherwise the service responds with the message, Service is temporarily down for maintenance
. If the service reports the system properties as desired, then the health of this service is UP
. If the service is down for maintenance, then its health is DOWN'. With this condtion set on the service, the second condition in the `isHealthy()
method of the InventoryHealth
class is relying on it.
The same condition is applied for the listContents()
method in this service. This method lists the stored hosts.
The serviceInMaintenance()
method from the class JsonMessages
is provided for
you to be used in this guide. To learn more about this class, read
Configuring Microservices using MicroProfile Config.
This method is used in this class to respond a Json Object containing a message telling the user
that the service is currently down for maintenance. You just need to pass the name of the service to it.
To build the application, run the Maven install goal from the command line:
mvn install
This goal builds the application and creates a .war file in the target directory. The goal also configures and installs Open Liberty into the target/liberty/wlp directory.
Next, run the Maven liberty:start-server goal:
mvn liberty:start-server
This goal starts an Open Liberty server instance. Your Maven pom.xml is already configured to start the application in this server instance.
Once the server is running, you can find the health endpoint reporting the state of the two services at the following URL:
-
http://localhost:9080/health
Now, try to turn the InventoryResource
service down (i.e. in maintenance) by changing the
property io_openliberty_guides_inventory_inMaintenance
value to true
. This property is found in
/finish/CustomConfigSource.json
. Refresh the browser. You will see the state of the
InventoryResource
is currently DOWN
and because of that the overall outcome is DOWN
. You can
verify that by pointing your browser to the inventory service endpoint. As you can see, the service is responding
with a message telling you that it is in maintenance.
If you make changes to the code, use the Maven package goal to rebuild the application and have the running Open Liberty server pick them up automatically:
mvn package
To stop the Open Liberty server, run the Maven liberty:stop-server goal:
mvn liberty:stop-server
You will write two test methods testIfServicesStatesUp()
and testIfInventoryTemporarilyDown()
to
validate the state of PropertiesResource
and InventoryResource
services. You will also use a
test helper class HealthTestUtil
that is already provided for you to perform these two tests.
Begin by creating a test class src/test/java/it/io/openliberty/guides/health/HealthTest.java:
link:finish/src/test/java/it/io/openliberty/guides/inventory/HealthTest.java[role=include]
The @Before and @After annotations are placed on methods that execute before and after every test
case. These methods are generally used to perform any setup and teardown tasks.
In this case, the setup()
method initializes the fields. They are the JsonArray
that hold the states
of the services, the two maps for storing the states when the services are up and when they are
down and the constant to hold the property that will be read. The teardown()
method simply resets
the property’s value.
There are few test case methods annotated with @Test
to test the functionality of the inventory
application after adding health checks.
-
The
testIfApplicationIsUp()
method checks if the application outcome is currentlyUP
. This means both services' healthy states areUP
. This test uses these helper methods:-
connectToHealthEnpoint()
method sends a request tohttp://localhost:9080/health
then verifies the200
response code is returned. This method also reads the response asJsonArray
which contains the states of the two services. TheJsonArray
is used to compare with the expected service states. -
getActualState()
method returns the state (UP
orDOWN
) of a specific service from theJsonArray
object that is passed as an argument to it. -
checkServicesStates()
method verifies and asserts the actual states of both services.
-
-
The
testIfInventoryServiceIsDown()
method follows the similar procedure as in the previous test case. It first checks if the application outcome isUP
. Next, theio.openliberty.guides.microprofile.inventory.inMaintenance
property value is changed fromfalse
totrue
in theCustomConfigSource.json
file. With the property update, we send a request to check the health outcome again. This time the expected code should be 503. Lastly, we validate the state of theInventoryResource
service by asserting if it isDOWN
but theProeprtiesResource
service isUP
.
Go to start
directory and run mvn clean install
. You should see two tests pass with the following
results:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.microprofile.HealthTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.912 sec - in it.io.openliberty.guides.microprofile.HealthTest
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
You have learned how to add a health check to report the states of microservices such as REST in an application. Then you wrote tests to validate that.