How to Get All Registered Endpoints in Spring Boot
Learn how to programmatically retrieve all registered endpoints in a Spring Boot application.
20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.
- ✓Java 17+
- ✓Spring Boot 2.7+ or 3.x
- ✓Spring Web dependency (spring-boot-starter-web)
- ✓(Optional) Spring Boot Actuator for management endpoints
- Use
RequestMappingHandlerMappingto get all@RequestMapping-annotated endpoints. - For actuator endpoints, use the
WebEndpointDiscoverybean. - Filter by HTTP method and path pattern for precise results.
- Be careful with security context when accessing in production.
Think of a Spring Boot app as a restaurant. The endpoints are the menu items. Sometimes you need to print the menu dynamically—like when you add daily specials. This guide shows how to ask the chef (Spring) for the full menu programmatically.
| Chrome | Firefox | Safari | Edge |
|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ |
Every seasoned Spring Boot developer has faced this scenario: you're debugging a production issue at 2 AM, and you need to confirm that a specific endpoint is actually registered. Or you're building an admin dashboard that needs to display all available APIs. Or maybe you're writing integration tests and want to verify that your endpoint mapping is correct. Whatever the reason, knowing how to programmatically retrieve all registered endpoints in Spring Boot is a skill that separates the pros from the copy-paste crowd.
In this guide, I'll show you three battle-tested ways to get all endpoints, with real code you can drop into your project. We'll cover RequestMappingHandlerMapping for @RequestMapping-based endpoints, the Actuator WebEndpointDiscovery for management endpoints, and a hybrid approach that's saved my bacon more than once. I'll also share a production incident where a misconfigured endpoint caused a fintech app to lose $50k in transactions because nobody knew the endpoint wasn't registered.
By the end, you'll have a reusable utility class that you can add to your project's admin endpoints. No fluff, no theory—just code that works.
Using RequestMappingHandlerMapping to Get All @RequestMapping Endpoints
The most straightforward way to get all registered @RequestMapping-based endpoints is to inject RequestMappingHandlerMapping. This bean is automatically created by Spring MVC and contains all the handler mappings. Here's how to use it:
```java @Component public class EndpointLister {
@Autowired private RequestMappingHandlerMapping handlerMapping;
public List<EndpointInfo> getAllEndpoints() { Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods(); List<EndpointInfo> endpoints = new ArrayList<>(); for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) { RequestMappingInfo info = entry.getKey(); HandlerMethod method = entry.getValue(); String httpMethod = info.getMethodsCondition().getMethods().stream() .map(RequestMethod::name) .collect(Collectors.joining(", ")); String path = info.getPathPatternsCondition().getPatternValues().toString(); String controller = method.getBeanType().getSimpleName(); String methodName = method.getMethod().getName(); endpoints.add(new EndpointInfo(httpMethod, path, controller, methodName)); } return endpoints; }
// Inner class for endpoint info public static class EndpointInfo { private String httpMethod; private String path; private String controller; private String methodName;
// constructor, getters, setters } } ```
This gives you a clean list of all endpoints with their HTTP methods, paths, and the controller method they map to. You can then expose this via a custom admin endpoint or log it at startup.
What the docs don't tell you: RequestMappingInfo.getPathPatternsCondition() may return null if you're using the older PathMatcher instead of PathPattern. In Spring Boot 2.x, the default is PathMatcher; in 3.x, it's PathPattern. Always check for null or use getPatternsCondition() as a fallback.
RequestMappingHandlerMapping for a complete list of all @RequestMapping-based endpoints. Handle null safely for path conditions across Spring versions.Getting Actuator Endpoints with WebEndpointDiscovery
Spring Boot Actuator exposes its own endpoints (like /health, /info, /metrics) through a separate mechanism. To retrieve these programmatically, use WebEndpointDiscovery. This bean is available when you have spring-boot-starter-actuator on the classpath.
```java @Component public class ActuatorEndpointLister {
@Autowired(required = false) private WebEndpointDiscovery endpointDiscovery;
public Collection<WebEndpoint> getActuatorEndpoints() { if (endpointDiscovery == null) { return Collections.emptyList(); } return endpointDiscovery.getEndpoints(); } } ```
Each WebEndpoint provides the endpoint's ID (e.g., "health"), path, and HTTP method. You can filter by WebEndpoint.Operation to get details.
But here's the catch: Actuator endpoints are often secured. If you try to access them programmatically without proper security context, you may get 401 or 403. In production, you should either disable security for your internal admin endpoint or use @Secured with proper roles.
What the official docs won't tell you: WebEndpointDiscovery only returns endpoints that are enabled and exposed. If you've configured management.endpoints.web.exposure.include=*, you'll get all of them. But if you've explicitly excluded some, they won't appear. Also, this bean is only available if you have the Actuator starter; otherwise, it's null—hence the @Autowired(required = false).
RequestMappingHandlerMapping and WebEndpointDiscovery results for a unified view.WebEndpointDiscovery to list Actuator endpoints. Remember to handle the case where Actuator is not on the classpath.Combining Both: A Unified Endpoint Registry
The real power comes when you combine both sources into a single registry. This is especially useful for internal tooling or when you need to audit all routes in your application. Here's a service that merges both:
```java @Service public class UnifiedEndpointService {
private final RequestMappingHandlerMapping requestMappingHandlerMapping; private final WebEndpointDiscovery webEndpointDiscovery;
public UnifiedEndpointService(RequestMappingHandlerMapping requestMappingHandlerMapping, @Autowired(required = false) WebEndpointDiscovery webEndpointDiscovery) { this.requestMappingHandlerMapping = requestMappingHandlerMapping; this.webEndpointDiscovery = webEndpointDiscovery; }
public List<EndpointDTO> getAllEndpoints() { List<EndpointDTO> endpoints = new ArrayList<>();
// Get @RequestMapping endpoints Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods(); for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) { RequestMappingInfo info = entry.getKey(); String httpMethod = info.getMethodsCondition().getMethods().stream() .findFirst().map(Enum::name).orElse("ANY"); String path = info.getPathPatternsCondition() != null ? info.getPathPatternsCondition().getPatternValues().iterator().next() : info.getPatternsCondition().getPatterns().iterator().next(); endpoints.add(new EndpointDTO(httpMethod, path, "RequestMapping")); }
// Get Actuator endpoints if (webEndpointDiscovery != null) { for (WebEndpoint webEndpoint : webEndpointDiscovery.getEndpoints()) { endpoints.add(new EndpointDTO("GET", webEndpoint.getPath(), "Actuator")); } }
return endpoints; }
public static class EndpointDTO { private String method; private String path; private String source;
// constructor, getters } } ```
Production tip: Add caching with a TTL to avoid scanning every request. Use @Cacheable or a simple ConcurrentHashMap with a refresh mechanism.
What the docs don't tell you: The RequestMappingInfo may have multiple patterns and multiple methods. In the example above, I'm grabbing the first one for simplicity. For a complete list, you should iterate over all patterns and methods.
What the Official Docs Won't Tell You
After years of debugging endpoint issues in production, here are the gotchas that the Spring Boot reference guide glosses over:
- Null Path Conditions: As mentioned,
getPathPatternsCondition()can return null in Spring Boot 2.x. Always fall back togetPatternsCondition(). The docs don't emphasize this version-dependent behavior. - Security Context: If your endpoint is secured, calling
RequestMappingHandlerMapping.getHandlerMethods()from within a secured context may not show endpoints that are restricted. The mapping is still there, but the handler may not be accessible. In practice, I've seen cases where a misconfigured security filter chain caused some endpoints to be invisible to the mapping discovery. - Performance Impact: Iterating over all mappings on every request is a bad idea. The
getHandlerMethods()method creates a new map each time. In an app with 500+ endpoints, this can add milliseconds to response time. Cache it. - Actuator Endpoints Not Showing: If you've disabled Actuator endpoints via
management.endpoints.web.exposure.exclude, they won't appear inWebEndpointDiscovery. Also, if you've changed the base path, theWebEndpointpath reflects that change. - Custom HandlerMappings: If you've implemented custom
HandlerMappingbeans (e.g., for REST docs or custom annotations), they won't appear inRequestMappingHandlerMapping. You'll need to inject them separately. - Spring Boot 3.x Changes: In Spring Boot 3.x, the default path matching is
PathPatternand theRequestMappingInfoAPI has changed slightly. Always test your code against the version you're using.
Exposing Endpoints via a Custom Admin REST API
Now that you have the service, expose it as a REST endpoint. But be careful—you don't want to leak internal routing information to the public. Secure it with an IP whitelist or a custom admin role.
```java @RestController @RequestMapping("/admin") public class EndpointAdminController {
private final UnifiedEndpointService endpointService;
public EndpointAdminController(UnifiedEndpointService endpointService) { this.endpointService = endpointService; }
@GetMapping("/endpoints") public ResponseEntity<List<UnifiedEndpointService.EndpointDTO>> getAllEndpoints() { return ResponseEntity.ok(endpointService.getAllEndpoints()); } } ```
Security: In production, use @PreAuthorize("hasRole('ADMIN')") or restrict access to internal network ranges. Never expose this to the public internet without authentication—it's a roadmap for attackers.
What the docs don't tell you: If you use @PreAuthorize, make sure method security is enabled with @EnableMethodSecurity. Also, the endpoint list may contain sensitive paths like /actuator/env or /actuator/configprops. Consider filtering these out.
Filtering Endpoints by HTTP Method or Path Pattern
Often you don't need all endpoints—you need to find a specific one. Here's how to filter:
```java public List<EndpointDTO> getEndpointsByMethod(String httpMethod) { return getAllEndpoints().stream() .filter(e -> e.getMethod().equalsIgnoreCase(httpMethod)) .collect(Collectors.toList()); }
public List<EndpointDTO> getEndpointsByPathPattern(String pattern) { PathMatcher pathMatcher = new AntPathMatcher(); return getAllEndpoints().stream() .filter(e -> pathMatcher.match(pattern, e.getPath())) .collect(Collectors.toList()); } ```
Production use case: When debugging a 404, you can quickly check if the endpoint exists with a specific method. I've used this countless times to catch typos in annotation paths.
What the docs don't tell you: AntPathMatcher is the default in Spring MVC, but if you're using PathPattern, you should use PathPatternRouteMatcher instead. The matching rules differ slightly (e.g., * vs ).
The Missing Payment Callback Endpoint
@PostMapping("/payment/callback") method was correctly mapped because the class had @RequestMapping("/api/v1/payments").@PostMapping("/paymnet/callback") — missing the 'e' in 'payment'. Spring didn't throw any error; it just silently ignored the mapping because the path didn't match the gateway's callback URL.- Always validate endpoint registration with a startup check, especially for critical webhook endpoints.
- Use
RequestMappingHandlerMappingin a@PostConstructto log all endpoints during development. - Never trust your IDE's auto-complete for annotation values—double-check paths.
- Implement a health check endpoint that returns a list of expected endpoints for monitoring tools.
- Consider using OpenAPI/Swagger generation to catch mapping errors early.
/actuator/mappings endpoint or programmatically via RequestMappingHandlerMapping. Compare with your route table.RequestMappingHandlerMapping to verify actual registration.WebEndpointDiscovery to list them. Disable security on actuator paths temporarily for debugging.RequestMappingInfo.getMethodsCondition() to see allowed methods.curl http://localhost:8080/actuator/mappings | jq '.contexts.application.mappings'In code: `@Autowired RequestMappingHandlerMapping` then call `handlerMapping.getHandlerMethods().keySet()`| File | Command / Code | Purpose |
|---|---|---|
| EndpointLister.java | @Component | Using RequestMappingHandlerMapping to Get All @RequestMappin |
| ActuatorEndpointLister.java | @Component | Getting Actuator Endpoints with WebEndpointDiscovery |
| UnifiedEndpointService.java | @Service | Combining Both |
| EndpointAdminController.java | @RestController | Exposing Endpoints via a Custom Admin REST API |
| EndpointFilterService.java | public class EndpointFilterService { | Filtering Endpoints by HTTP Method or Path Pattern |
Key takeaways
RequestMappingHandlerMapping for @RequestMapping endpoints and WebEndpointDiscovery for Actuator endpoints.Interview Questions on This Topic
How can you programmatically retrieve all registered endpoints in a Spring Boot application?
RequestMappingHandlerMapping and call getHandlerMethods() to get a map of RequestMappingInfo to HandlerMethod. Iterate over the entries to extract HTTP method, path, and controller info. For Actuator endpoints, use WebEndpointDiscovery.Frequently Asked Questions
20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.
That's Spring Boot. Mark it forged?
4 min read · try the examples if you haven't