Introduction
Here we will see example on creating custom endpoints in Spring Boot Actuator. There are a number of endpoints provided by Spring Boot however we may want to create a custom endpoint using Spring Boot Actuator.
We have seen few examples on Spring Boot actuators:
- Spring Boot Actuator Example
- Spring Boot Actuator – Accessing Endpoints via JMX
- Spring Boot Actuator – Securing Endpoints
Prerequisites
First go through the example Spring Boot Actuator – Production Ready Features
Custom Endpoints
If you add a @Bean
annotated with @Endpoint
, any methods annotated with @ReadOperation
, @WriteOperation
, or @DeleteOperation
are automatically exposed over JMX and, in a web application, over HTTP as well. Endpoints can be exposed over HTTP using Jersey, Spring MVC, or Spring WebFlux.
You can also write technology-specific endpoints by using @JmxEndpoint
(exposed only over JMX and not over HTTP) or @WebEndpoint
(exposed only over HTTP and not over JMX).
You can write technology-specific extensions by using @EndpointWebExtension
and @EndpointJmxExtension
. These annotations let you provide technology-specific operations to augment an existing endpoint.
Finally, if you need access to web-framework-specific functionality, you can implement Servlet or Spring @Controller
and @RestController
endpoints at the cost of them not being available over JMX or when using a different web framework.
Here we will see examples on @Endpoint
, @ControllerEndpoint
and @RestControllerEndpoint
.
VO class
Create below VO (Value Object) class, which is a POJO class holds data or value and does nothing special.
package com.roytuts.springboot.actuator.vo;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
@Endpoint
Create below class, which is annotated with @Endpoint
and it means that we are creating custom endpoint using Spring Boot Actuator.
The class must have @Component
annotation in order to let container pick up the class.
You must provide a unique id to the endpoint in order to identify it.
We have shown here @ReadOperation
, which is equivalent to HTTP GET request. You can also create other operations, such as, @WriteOperation
(POST), @DeleteOperation
(DELETE).
We have taken an input as a query parameter called name
in sayHello()
method. If you do not provide any name to the parameter then it will automatically pick the name as variable name. Here it is “String name”, so the parameter name is “name”.
package com.roytuts.springboot.actuator.endpoint;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;
import com.roytuts.springboot.actuator.vo.Greeting;
@Component
@Endpoint(id = "hello-endpoint")
public class GreetingEndpoint {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@ReadOperation
public Greeting sayHello(@RequestParam(defaultValue = "Stranger") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
@ControllerEndpoint and @RestControllerEndpoint
@ControllerEndpoint
and @RestControllerEndpoint
can be used to implement an endpoint that is only exposed by Spring MVC or Spring WebFlux. Methods are mapped using the standard annotations for Spring MVC and Spring WebFlux such as @RequestMapping
and @GetMapping
, with the endpoint’s ID being used as a prefix for the path. Controller endpoints provide deeper integration with Spring’s web frameworks but at the expense of portability. The @Endpoint
and @WebEndpoint
annotations should be preferred whenever possible.
@ControllerEndpoint
You must provide a unique id to the endpoint in order to identify it.
We have used @ResponseBody
because we want response to be displayed directly on the body of the response rather than using a view file, such as, jsp.
package com.roytuts.springboot.actuator.endpoint;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.roytuts.springboot.actuator.vo.Greeting;
@Component
@ControllerEndpoint(id = "controller-endpoint")
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@ResponseBody
@GetMapping("/hello")
public Greeting greet(@RequestParam(defaultValue = "Stranger") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
@RestControllerEndpoint
You must provide a unique id to the endpoint in order to identify it.
package com.roytuts.springboot.actuator.endpoint;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.roytuts.springboot.actuator.vo.Greeting;
@Component
@RestControllerEndpoint(id = "rest-controller-endpoint")
public class GreetingRestController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@GetMapping("/hello")
public ResponseEntity<Greeting> greet(@RequestParam(defaultValue = "Stranger") String name) {
return new ResponseEntity<Greeting>(new Greeting(counter.incrementAndGet(), String.format(template, name)),
HttpStatus.OK);
}
}
Exposing Endpoints
Now either you can expose only the endpoints you have created above or you can expose all endpoints including the above endpoints.
If you want to expose all endpoints then add below line to application.properties file:
management.endpoints.web.exposure.include=*
If you want to expose only the above endpoints, which you have created then add below line to the application.properties file:
management.endpoints.web.exposure.include=hello-endpoint,controller-endpoint,rest-controller-endpoint
Main Class
The main class helps you to start and deploy the Spring Boot application into embedded Tomcat server.
package com.roytuts.springboot.actuator.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.roytuts.springboot.actuator")
public class ActuatorApplication {
public static void main(String[] args) {
SpringApplication.run(ActuatorApplication.class, args);
}
}
Testing the Application
Run the above main class to deploy the application.
Now hit the URLs either from REST client or in the browser directly.
You will get same output for the below URLs:
http://localhost:8080/actuator/hello-endpoint?name=Soumitra
http://localhost:8080/actuator/controller-endpoint/hello?name=Soumitra
http://localhost:8080/actuator/rest-controller-endpoint/hello?name=Soumitra

You will get same output for the below URLs:
http://localhost:8080/actuator/controller-endpoint/hello
http://localhost:8080/actuator/rest-controller-endpoint/hello

Source Code
Thanks for reading.
I really like all Spring Boot applications. All the Best