Home Java How to Get All Registered Endpoints in Spring Boot
Intermediate 4 min · July 14, 2026

How to Get All Registered Endpoints in Spring Boot

Learn how to programmatically retrieve all registered endpoints in a Spring Boot application.

N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.

Follow
Production
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
Before you start⏱ 15-20 min read
  • Java 17+
  • Spring Boot 2.7+ or 3.x
  • Spring Web dependency (spring-boot-starter-web)
  • (Optional) Spring Boot Actuator for management endpoints
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Use RequestMappingHandlerMapping to get all @RequestMapping-annotated endpoints.
  • For actuator endpoints, use the WebEndpointDiscovery bean.
  • Filter by HTTP method and path pattern for precise results.
  • Be careful with security context when accessing in production.
✦ Definition~90s read
What is How to Get All Registered Endpoints in Spring Boot?

Getting all registered endpoints in Spring Boot means programmatically retrieving the list of HTTP routes (paths and methods) that your application exposes, including both controller endpoints and Actuator management endpoints.

Think of a Spring Boot app as a restaurant.
Plain-English First

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.

⚙ Browser compatibility
Latest versions — ✓ supported
ChromeFirefoxSafariEdge

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.

EndpointLister.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@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() != null ?
                    info.getPathPatternsCondition().getPatternValues().toString() :
                    info.getPatternsCondition().getPatterns().toString();
            String controller = method.getBeanType().getSimpleName();
            String methodName = method.getMethod().getName();
            endpoints.add(new EndpointInfo(httpMethod, path, controller, methodName));
        }
        return endpoints;
    }

    public static class EndpointInfo {
        private String httpMethod;
        private String path;
        private String controller;
        private String methodName;

        public EndpointInfo(String httpMethod, String path, String controller, String methodName) {
            this.httpMethod = httpMethod;
            this.path = path;
            this.controller = controller;
            this.methodName = methodName;
        }

        public String getHttpMethod() { return httpMethod; }
        public String getPath() { return path; }
        public String getController() { return controller; }
        public String getMethodName() { return methodName; }
    }
}
Output
Example output from getAllEndpoints():
[
EndpointInfo{httpMethod='GET', path='[/api/users]', controller='UserController', methodName='getAllUsers'},
EndpointInfo{httpMethod='POST', path='[/api/users]', controller='UserController', methodName='createUser'},
EndpointInfo{httpMethod='GET', path='[/api/users/{id}]', controller='UserController', methodName='getUserById'}
]
⚠ Thread Safety & Caching
📊 Production Insight
In a production environment with hundreds of endpoints, iterating over all mappings can be expensive. Cache the result and invalidate only when the context refreshes.
🎯 Key Takeaway
Use 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).

ActuatorEndpointLister.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.web.WebEndpoint;
import org.springframework.boot.actuate.endpoint.web.WebEndpointDiscovery;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;

@Component
public class ActuatorEndpointLister {

    @Autowired(required = false)
    private WebEndpointDiscovery endpointDiscovery;

    public Collection<WebEndpoint> getActuatorEndpoints() {
        if (endpointDiscovery == null) {
            return Collections.emptyList();
        }
        return endpointDiscovery.getEndpoints();
    }
}
Output
Example output from getActuatorEndpoints():
[WebEndpoint{id='health', path='/actuator/health', method='GET'},
WebEndpoint{id='info', path='/actuator/info', method='GET'},
WebEndpoint{id='metrics', path='/actuator/metrics', method='GET'}]
Note: The actual output depends on your Actuator configuration.
🔥Actuator Path Prefix
📊 Production Insight
In production, you might want to expose a custom admin endpoint that combines both RequestMappingHandlerMapping and WebEndpointDiscovery results for a unified view.
🎯 Key Takeaway
Use 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.

UnifiedEndpointService.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.web.WebEndpoint;
import org.springframework.boot.actuate.endpoint.web.WebEndpointDiscovery;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@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;

        public EndpointDTO(String method, String path, String source) {
            this.method = method;
            this.path = path;
            this.source = source;
        }

        public String getMethod() { return method; }
        public String getPath() { return path; }
        public String getSource() { return source; }
    }
}
Output
Sample output:
[
EndpointDTO{method='GET', path='/api/users', source='RequestMapping'},
EndpointDTO{method='POST', path='/api/users', source='RequestMapping'},
EndpointDTO{method='GET', path='/actuator/health', source='Actuator'},
EndpointDTO{method='GET', path='/actuator/info', source='Actuator'}
]
💡Lombok for DTOs
📊 Production Insight
In a microservices environment, you might want to aggregate endpoint info from all services into a central registry. This service can be exposed as a REST endpoint and consumed by a gateway.
🎯 Key Takeaway
Combine both sources for a complete view. Cache the result to avoid performance hits.

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:

  1. Null Path Conditions: As mentioned, getPathPatternsCondition() can return null in Spring Boot 2.x. Always fall back to getPatternsCondition(). The docs don't emphasize this version-dependent behavior.
  2. 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.
  3. 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.
  4. Actuator Endpoints Not Showing: If you've disabled Actuator endpoints via management.endpoints.web.exposure.exclude, they won't appear in WebEndpointDiscovery. Also, if you've changed the base path, the WebEndpoint path reflects that change.
  5. Custom HandlerMappings: If you've implemented custom HandlerMapping beans (e.g., for REST docs or custom annotations), they won't appear in RequestMappingHandlerMapping. You'll need to inject them separately.
  6. Spring Boot 3.x Changes: In Spring Boot 3.x, the default path matching is PathPattern and the RequestMappingInfo API has changed slightly. Always test your code against the version you're using.
⚠ Version Matters
📊 Production Insight
Always log the number of registered endpoints at startup. A sudden drop can indicate a missing component scan or a failed bean registration.
🎯 Key Takeaway
Be aware of version-specific behavior, security implications, and performance considerations. The official docs often omit these real-world nuances.

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.

EndpointAdminController.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/admin")
public class EndpointAdminController {

    private final UnifiedEndpointService endpointService;

    public EndpointAdminController(UnifiedEndpointService endpointService) {
        this.endpointService = endpointService;
    }

    @GetMapping("/endpoints")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<List<UnifiedEndpointService.EndpointDTO>> getAllEndpoints() {
        return ResponseEntity.ok(endpointService.getAllEndpoints());
    }
}
Output
HTTP GET /admin/endpoints (with ADMIN role)
Response:
[
{"method":"GET","path":"/api/users","source":"RequestMapping"},
{"method":"POST","path":"/api/users","source":"RequestMapping"},
{"method":"GET","path":"/actuator/health","source":"Actuator"}
]
🔥Enable Method Security
📊 Production Insight
In production, I've seen teams accidentally expose this to the public because they forgot to add security. Always double-check your security configuration with a penetration test.
🎯 Key Takeaway
Expose endpoint info via a secured admin endpoint. Use role-based access control and filter sensitive paths.

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 ).

EndpointFilterService.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.List;
import java.util.stream.Collectors;

public class EndpointFilterService {

    private final UnifiedEndpointService endpointService;

    public EndpointFilterService(UnifiedEndpointService endpointService) {
        this.endpointService = endpointService;
    }

    public List<UnifiedEndpointService.EndpointDTO> getEndpointsByMethod(String httpMethod) {
        return endpointService.getAllEndpoints().stream()
                .filter(e -> e.getMethod().equalsIgnoreCase(httpMethod))
                .collect(Collectors.toList());
    }

    public List<UnifiedEndpointService.EndpointDTO> getEndpointsByPathPattern(String pattern) {
        PathMatcher pathMatcher = new AntPathMatcher();
        return endpointService.getAllEndpoints().stream()
                .filter(e -> pathMatcher.match(pattern, e.getPath()))
                .collect(Collectors.toList());
    }
}
Output
Example: getEndpointsByMethod("POST") returns only POST endpoints.
Example: getEndpointsByPathPattern("/api/**") returns all endpoints under /api/.
💡Use PathPattern for Spring Boot 3.x
📊 Production Insight
When you have hundreds of endpoints, filtering is essential. I once debugged a production issue where a misconfigured filter chain caused all POST endpoints to return 405. Filtering by method instantly revealed the problem.
🎯 Key Takeaway
Filtering by method or path pattern helps quickly locate specific endpoints. Use the appropriate path matcher for your Spring version.
● Production incidentPOST-MORTEMseverity: high

The Missing Payment Callback Endpoint

Symptom
Users reported that payments were deducted from their accounts but the order status never changed to 'Paid'. The payment gateway confirmed callbacks were being sent to the server.
Assumption
The developer assumed the new @PostMapping("/payment/callback") method was correctly mapped because the class had @RequestMapping("/api/v1/payments").
Root cause
The method had a typo in the annotation: @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.
Fix
We added a startup listener that logs all registered endpoints and compares them against a known list. The typo was immediately visible. After fixing the path, payments processed correctly.
Key lesson
  • Always validate endpoint registration with a startup check, especially for critical webhook endpoints.
  • Use RequestMappingHandlerMapping in a @PostConstruct to 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.
Production debug guideSymptom to Action4 entries
Symptom · 01
A client reports 404 on a new endpoint that should exist.
Fix
Check if the endpoint is registered using the /actuator/mappings endpoint or programmatically via RequestMappingHandlerMapping. Compare with your route table.
Symptom · 02
Swagger UI shows endpoints that don't work.
Fix
Swagger often reads from the same mapping source. If it shows the endpoint, the issue is likely in the method implementation or security config. Use RequestMappingHandlerMapping to verify actual registration.
Symptom · 03
Actuator health check fails but the app seems fine.
Fix
Check if actuator endpoints themselves are registered. Use WebEndpointDiscovery to list them. Disable security on actuator paths temporarily for debugging.
Symptom · 04
Endpoints are registered but return 405 Method Not Allowed.
Fix
Check if the correct HTTP method is mapped. Use RequestMappingInfo.getMethodsCondition() to see allowed methods.
★ Quick Debug Cheat SheetQuick commands to diagnose endpoint registration issues.
Endpoint not found (404)
Immediate action
Check if the endpoint is registered via Actuator or code.
Commands
curl http://localhost:8080/actuator/mappings | jq '.contexts.application.mappings'
In code: `@Autowired RequestMappingHandlerMapping` then call `handlerMapping.getHandlerMethods().keySet()`
Fix now
Fix the annotation path or ensure the controller is component-scanned.
Wrong HTTP method returns 405+
Immediate action
Check allowed methods for the endpoint.
Commands
curl -v -X DELETE http://localhost:8080/api/resource
In code: `handlerMapping.getHandlerMethods().forEach((info, method) -> info.getMethodsCondition().getMethods())`
Fix now
Update the @RequestMapping method attribute or use specific @GetMapping etc.
Endpoint exists but returns 403 Forbidden+
Immediate action
Check security configuration for that path.
Commands
Check Spring Security logs for 'FilterInvocation'
In code: `@Autowired SecurityFilterChain` chain...
Fix now
Add .permitAll() or adjust security rules in SecurityFilterChain.
ApproachSourceIncludes ActuatorSpring VersionPerformance
RequestMappingHandlerMappingController annotationsNo2.x, 3.xMedium (cache recommended)
WebEndpointDiscoveryActuator endpointsYes2.x, 3.xFast
CombinedBothYes2.x, 3.xMedium (cache recommended)
Actuator HTTP endpoint (/actuator/mappings)Controller + ActuatorYes2.x, 3.xFast (built-in)
⚙ Quick Reference
5 commands from this guide
FileCommand / CodePurpose
EndpointLister.java@ComponentUsing RequestMappingHandlerMapping to Get All @RequestMappin
ActuatorEndpointLister.java@ComponentGetting Actuator Endpoints with WebEndpointDiscovery
UnifiedEndpointService.java@ServiceCombining Both
EndpointAdminController.java@RestControllerExposing Endpoints via a Custom Admin REST API
EndpointFilterService.javapublic class EndpointFilterService {Filtering Endpoints by HTTP Method or Path Pattern

Key takeaways

1
Use RequestMappingHandlerMapping for @RequestMapping endpoints and WebEndpointDiscovery for Actuator endpoints.
2
Cache the endpoint list to avoid performance degradation in production.
3
Handle null path conditions to support both Spring Boot 2.x and 3.x.
4
Always secure your admin endpoint that exposes routing information.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
How can you programmatically retrieve all registered endpoints in a Spri...
Q02SENIOR
What are the potential pitfalls when using `RequestMappingHandlerMapping...
Q03SENIOR
How would you expose a list of all endpoints via a REST API securely?
Q01 of 03SENIOR

How can you programmatically retrieve all registered endpoints in a Spring Boot application?

ANSWER
Inject 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.
FAQ · 3 QUESTIONS

Frequently Asked Questions

01
Can I get endpoints that are defined via XML or Java config (not annotations)?
02
How do I get endpoints from a specific controller only?
03
Will this work with WebFlux (reactive stack)?
N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.

Follow
Verified
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
🔥

That's Spring Boot. Mark it forged?

4 min read · try the examples if you haven't

Previous
Setting a Request Timeout for a Spring REST API
106 / 121 · Spring Boot
Next
Making Multiple REST Calls in Parallel with CompletableFuture in Spring