Spring Boot Actuator Example
The Spring Boot Actuator helps you monitor and manage your application when you deploy it to production. Monitoring, gathering metrics, understanding the state of your app, etc. can be automatically applied when using this library. There are two ways of managing and monitoring your application, HTTP endpoint and JMX. This example demonstrates the HTTP endpoint.
1. Tools
2. Assumptions
This article assumes that you know your way around Eclipse. You are familiar with Maven. Basically, you have done some coding. This project has been created using Eclipse Mars so all instructions are based on this IDE.
3. Project Setup
To start, create your project. This can be done by going to File -> New -> Maven Project and fill up what is required.
4. Project Object Model
Your pom.xml
should look like the one below:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.example</groupId> <artifactId>spring-boot-actuator</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> <maven-jar-plugin.version>2.6</maven-jar-plugin.version> <!-- fixes Eclipse Mars m2e error in MavenArchiver.getManifest() --> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The simplest way to enable the Spring Boot Actuator features is to add the spring-boot-starter-actuator
dependency. You may not need the maven-jar-plugin.version
property if you have updated your Eclipse m2e extensions. You are using spring-boot-starter-web
because you’re doing HTTP endpoints. You’re also using spring-boot-starter-security
because you will be overriding the default actuator setting. In Eclipse, you can see the dependency hierarchy by opening the pom.xml
and clicking on the Dependency Hierarchy tab. The Spring Boot Maven plugin enables you to package the project as an executable jar.
5. Create the Web App
Main.java
package com.javacodegeeks.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } }
This is just a simple code to get your web application up and running. Instead of annotating your class with @Configuration
, @EnableAutoConfiguration
, and @ComponentScan
, you use the @SpringBootApplication
annotation as a convenient alternative. This annotation tells Spring Boot to scan for other components, add beans based on the classpath, and tags the class as a source of bean definitions. You should be able to run (Run As -> Java Application) the web application and access it on localhost or use the curl command.
Console Output
... 2018-03-17 17:54:24.056 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.058 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.059 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.060 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/conditions],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.061 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.062 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.064 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.065 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) 2018-03-17 17:54:24.066 INFO 8244 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map) ...
You should see something like the lines above in your console output. This means that your actuator is working and ready to serve. These are the available actuator endpoints.
6. Enable Endpoints
By default all endpoints are enabled except for shutdown
. The syntax to configure the enablement of an endpoit is management.endpoit.<id>.enabled
. To enable the shutdown
endpoint, add the line below to your application.properties
(or YML) file.
application.properties
management.endpoint.shutdown.enabled=true
7. Expose All Endpoints
This is not a good idea to do in a production environment but for learning purposes you are going to do it. Endpoints contain sensitive information, so you must choose wisely what to expose. To expose all the endpoints, add the line below to your properties file.
application.properties
management.endpoints.web.exposure.include=*
Next is to configure Spring Security to allow you to access the endpoints.
MainSecurity.java
package com.javacodegeeks.example; import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class MainSecurity extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests() .anyRequest().permitAll(); } }
The code above allows all endpoint requests to be permitted. Happy days! You should now be able to access /actuator/health
, /actuator/beans
, /actuator/heapdump
, etc. and see some JSON response.
/actuator/env
{ "activeProfiles": [], "propertySources": [ { "name": "server.ports", "properties": { "local.management.port": { "value": 9090 }, "local.server.port": { "value": 8080 } } }, { "name": "servletContextInitParams", "properties": {} }, { "name": "systemProperties", "properties": { "java.runtime.name": { "value": "Java(TM) SE Runtime Environment" }, "sun.boot.library.path": { "value": "C:\\Program Files\\Java\\jre1.8.0_121\\bin" },
The response above is a JSON excerpt of the /actuator/env
endpoint.
8. Customizing Endpoint Path and Port
Use the management.endpoints.web.base-path
property to change the prefix of your endpoint. The example below sets your endpoint path to start with /monitoring
. So instead of /actuator/health
, it will now be /monitoring/health
.
application.properties
management.endpoints.web.base-path=/monitoring
Use the management.server.port
property to change the management server’s HTTP port. The example below sets your port to 9090. So the server is accessible at http://localhost:9090/actuator/health.
application.properties
management.server.port=9090
9. Custom Application Information
Hitting /actuator/info
displays your application information. To add your own custom application information, set the info.*
Spring properties.
application.properties
info.app.encoding=UTF-8 info.app.java.source=1.7 info.app.java.target=1.7 info.app.motd=Spring Boot Actuator Example
Below is the result when hitting /actuator/info
again with the above configuration.
/actuator/info JSON response
{ "app": { "encoding": "UTF-8", "java": { "source": "1.7", "target": "1.7" }, "motd": "Spring Boot Actuator Example" } }
Alternatively, if you’re using spring-boot-starter-parent
, you can refer to your Maven project properties with @..@
placeholders. So the above example will look like below:
application.properties
info.app.encoding=@project.build.sourceEncoding@ info.app.java.source=@java.version@ info.app.java.target=@java.version@ info.app.motd=Spring Boot Actuator Example
10. Custom Health Information
The default response when hitting /actuator/health
is UP, DOWN, UNKNOWN, or OUT_OF_SERVICE. To provide more health information, you need to register Spring beans that implement the HealthIndicator
interface.
MainHealthIndicator.java
package com.javacodegeeks.example; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; @Component public class MainHealthIndicator implements HealthIndicator { @Override public Health health() { return Health.down().withDetail("Memory Usage", "Limit reached.").build(); } }
You must provide an implementation of the health()
method and return a Health
response. The Health
response must include a status, in this case it’s DOWN. Optionally, you can add details to be displayed.
Below is the result when hitting /actuator/health
with the above health indicator implementation.
/actuator/health JSON response
{ "status": "DOWN", "details": { "main": { "status": "DOWN", "details": { "Memory Usage": "Limit reached." } }, "diskSpace": { "status": "UP", "details": { "total": 243164770304, "free": 72515084288, "threshold": 10485760 } } } }
11. Your Own Web Endpoint
You can also add your very own endpoint. You simply create a bean and annotate it with @Endpoint
and annotate your method with @ReadOperation
. For the sake of simplicity, the example below will just respond with the word of the day but this is where your monitoring logic should be.
WotdEndpoint.java
package com.javacodegeeks.example; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.stereotype.Component; @Component @Endpoint(id = "wotd", enableByDefault = true) public class WotdEndpoint { @ReadOperation public String wordOfTheDay() { return "{\"wotd\": \"Brilliant\"}"; } }
/actuator/wotd JSON response
{"wotd": "Brilliant"}
12. Spring Boot Actuator Summary
There you have it. Are you now more familiar with Spring Boot Actuator? In this example, you were able to use the actuators for your web application, enabled and exposed your endpoints. Furthermore, you created your own endpoint, customized existing endpoint output, and changed the endpoint path and the management server port. For more information go to Spring Data Actuator.
13. Download the Source Code
This is an example about Spring Boot Actuator.
You can download the source code of this example here: spring-boot-actuator.zip.