We have already seen how dropwizard is so effective in developing self-contained REST APIs and even REST client services as well. Dropwizard contains almost all needed packages to build APIs in very easy way without making the things complex. One of the easily implemented features of dropwizard is health check service which can be used for monitoring the status of the application/components that you are creating – in runtime.
Implementing Dropwizard Health Check
DropWizard health check is implemented by extending the HealthCheck
class and returning Result.healthy()
if everything is alright and Result.unhealthy()
if something is not working – as expected.
Health Check Configuration
public class AppHealthCheck extends HealthCheck { @Override protected Result check() throws Exception { if(Check some condition == true){ return Result.healthy(); } return Result.unhealthy("Error message"); } }
To register this AppHealthCheck
class with dropwizard application, use Environment.healthChecks()
registry.
public void run(Configuration c, Environment e) throws Exception { //Application health check e.healthChecks().register("APIHealthCheck", new AppHealthCheck()); }
Validating System Health
Dropwizard will a HTTP resource endpoint on /healthcheck
on the admin port (default 8081). Dropwizard also includes a check for deadlocks by default along with any custom health checks you define as in our case AppHealthCheck
.
http://localhost:8081/healthcheck
Above health check URL will return some result as below:
{ "APIHealthCheck": { "healthy": true }, "deadlocks": { "healthy": true } }
Custom REST Resource to Run Health Checks
If you do not want to use admin port then you can also create a custom REST resource which will run health checks for you, and return the result in your desired response format.
To run all health checks and get all it’s results, you will call registry.runHealthChecks()
inside REST resource.
@Produces(MediaType.APPLICATION_JSON) @Path("/status") public class HealthCheckController { private HealthCheckRegistry registry; public HealthCheckController(HealthCheckRegistry registry) { this.registry = registry; } @GET public Set<Entry<String, Result>> getStatus(){ return registry.runHealthChecks().entrySet(); } }
Now when we call this REST API using http://localhost:8080/status
, we get response like below:
[ { "APIHealthCheck": { "healthy": true, "message": null, "error": null } }, { "deadlocks": { "healthy": true, "message": null, "error": null } } ]
You can customize the messages as per your need.
Dropwizard Health Check Example
To demonstrate the above both functionalities, I have modified the code given in dropwizard hello world application.
AppHealthCheck.java
package com.howtodoinjava.healthcheck; import java.util.ArrayList; import javax.ws.rs.client.Client; import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.codahale.metrics.health.HealthCheck; public class AppHealthCheck extends HealthCheck { private final Client client; public AppHealthCheck(Client client) { super(); this.client = client; } @Override protected Result check() throws Exception { WebTarget webTarget = client.target("http://localhost:8080/employees"); Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); Response response = invocationBuilder.get(); @SuppressWarnings("rawtypes") ArrayList employees = response.readEntity(ArrayList.class); if(employees !=null && employees.size() > 0){ return Result.healthy(); } return Result.unhealthy("API Failed"); } }
HealthCheckController.java
package com.howtodoinjava.healthcheck; import java.util.Map.Entry; import java.util.Set; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import com.codahale.metrics.health.HealthCheck.Result; import com.codahale.metrics.health.HealthCheckRegistry; @Produces(MediaType.APPLICATION_JSON) @Path("/status") public class HealthCheckController { private HealthCheckRegistry registry; public HealthCheckController(HealthCheckRegistry registry) { this.registry = registry; } @GET public Set<Entry<String, Result>> getStatus(){ return registry.runHealthChecks().entrySet(); } }
App.java
package com.howtodoinjava.rest; import io.dropwizard.Application; import io.dropwizard.Configuration; import io.dropwizard.client.JerseyClientBuilder; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import javax.ws.rs.client.Client; import com.howtodoinjava.healthcheck.AppHealthCheck; import com.howtodoinjava.healthcheck.HealthCheckController; import com.howtodoinjava.rest.controller.EmployeeRESTController; import com.howtodoinjava.rest.controller.RESTClientController; public class App extends Application<Configuration> { @Override public void initialize(Bootstrap<Configuration> b) { } @Override public void run(Configuration c, Environment e) throws Exception { e.jersey().register(new EmployeeRESTController(e.getValidator())); final Client client = new JerseyClientBuilder(e).build("DemoRESTClient"); e.jersey().register(new RESTClientController(client)); //Application health check e.healthChecks().register("APIHealthCheck", new AppHealthCheck(client)); //Run multiple health checks e.jersey().register(new HealthCheckController(e.healthChecks())); } public static void main(String[] args) throws Exception { new App().run(args); } }
Validate Health Check URLs
1) http://localhost:8081/healthcheck

2) http://localhost:8080/status

Let me know of your questions in comments section.
Happy Learning !!
Reference:
Leave a Reply