Skip to content

Overhaul the mappings endpoint #9979

@wilkinsona

Description

@wilkinsona
Member

The mappings endpoint is currently described as returning "a collated list of all @RequestMapping paths". It actually returns more than that as it introspects any AbstractUrlHandlerMapping and AbstractHandlerMethodMapping instances, not just those that are associated with @RequestMapping. However, there are some mappings that it doesn't currently return such as those configured by Spring Data REST.

Beyond the accuracy of the description, the content of the response is a little haphazard. It currently looks like this:

{
    "/**": {
        "bean": "resourceHandlerMapping"
    },
    "/**/favicon.ico": {
        "bean": "faviconHandlerMapping"
    },
    "/webjars/**": {
        "bean": "resourceHandlerMapping"
    },
    "{[/application/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}": {
        "bean": "webEndpointServletHandlerMapping",
        "method": "public java.lang.Object org.springframework.boot.endpoint.web.mvc.WebEndpointServletHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)"
    },
    "{[/application/autoconfig],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}": {
        "bean": "webEndpointServletHandlerMapping",
        "method": "public java.lang.Object org.springframework.boot.endpoint.web.mvc.WebEndpointServletHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)"
    },
    "{[/application/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}": {
        "bean": "webEndpointServletHandlerMapping",
        "method": "public java.lang.Object org.springframework.boot.endpoint.web.mvc.WebEndpointServletHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)"
    }
    // …
}

The keys in the map are just the toString() of the mapping object which can, essentially, be anything. As such, there's no guarantee of the format of the key. There's also, as far as I know, no guarantee that the keys will be unique across everything that's introspected so entries in the map may clash. Lastly, handler mappings are ordered and this ordering is lost by using a map.

We also need to figure out what, if anything, we want to do for WebFlux and Jersey. Perhaps they should be completely separate endpoints? However, if you're using a combination of MVC and Jersey it might be nice to have all mappings available from a single source.

Activity

wilkinsona

wilkinsona commented on Sep 7, 2017

@wilkinsona
MemberAuthor

I've opened some Framework issues that all relate to this:

added this to the 2.0.0.M6 milestone on Sep 22, 2017
wilkinsona

wilkinsona commented on Sep 27, 2017

@wilkinsona
MemberAuthor

Let's try and also include information about Filters and Servlets too (previously tracked by #2178).

wilkinsona

wilkinsona commented on Nov 1, 2017

@wilkinsona
MemberAuthor

Here's an example of a what the response might look like for an app using Spring MVC and Spring Data REST:

{
    "dispatcherServlets": {
        "dispatcherServlet": [
            {
                "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@20de1a03]]",
                "predicate": "/**/favicon.ico"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/autoconfig],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/status],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/trace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/heapdump],methods=[GET],produces=[application/octet-stream]}"
            },
            {
                "handler": "private java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest)",
                "predicate": "{[/application],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)",
                "predicate": "{[/error]}"
            },
            {
                "handler": "public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)",
                "predicate": "{[/error],produces=[text/html]}"
            },
            {
                "handler": "org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.alps.AlpsController.alpsOptions()",
                "predicate": "{[/api/profile/{repository}],methods=[OPTIONS],produces=[application/alps+json]}"
            },
            {
                "handler": "org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.RootResourceInformation> org.springframework.data.rest.webmvc.alps.AlpsController.descriptor(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/profile/{repository}],methods=[GET],produces=[application/alps+json || */*]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.ProfileController.profileOptions()",
                "predicate": "{[/api/profile],methods=[OPTIONS]}"
            },
            {
                "handler": "org.springframework.http.HttpEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.ProfileController.listAllFormsOfMetadata()",
                "predicate": "{[/api/profile],methods=[GET]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.json.JsonSchema> org.springframework.data.rest.webmvc.RepositorySchemaController.schema(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/profile/{repository}],methods=[GET],produces=[application/schema+json]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositoryController.optionsForRepositories()",
                "predicate": "{[/api/ || /api],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryController.headForRepositories()",
                "predicate": "{[/api/ || /api],methods=[HEAD],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.RepositoryLinksResource> org.springframework.data.rest.webmvc.RepositoryController.listRepositories()",
                "predicate": "{[/api/ || /api],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.optionsForCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/{repository}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.headCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}],methods=[HEAD],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.hateoas.Resources<?> org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.hateoas.Resources<?> org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResourceCompact(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}],methods=[POST],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.optionsForItemResource(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/{repository}/{id}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.headForItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}/{id}],methods=[HEAD],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.Resource<?>> org.springframework.data.rest.webmvc.RepositoryEntityController.getItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.http.HttpHeaders) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}/{id}],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.putItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.data.rest.webmvc.support.ETag,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}/{id}],methods=[PUT],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.patchItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.data.rest.webmvc.support.ETag,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException,org.springframework.data.rest.webmvc.ResourceNotFoundException",
                "predicate": "{[/api/{repository}/{id}],methods=[PATCH],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.deleteItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.support.ETag) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                "predicate": "{[/api/{repository}/{id}],methods=[DELETE],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.data.rest.webmvc.RepositorySearchesResource org.springframework.data.rest.webmvc.RepositorySearchController.listSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/{repository}/search],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.optionsForSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/{repository}/search],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.headForSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                "predicate": "{[/api/{repository}/search],methods=[HEAD],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.util.MultiValueMap<java.lang.String, java.lang.Object>,java.lang.String,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.http.HttpHeaders)",
                "predicate": "{[/api/{repository}/search/{search}],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.hateoas.ResourceSupport org.springframework.data.rest.webmvc.RepositorySearchController.executeSearchCompact(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.http.HttpHeaders,org.springframework.util.MultiValueMap<java.lang.String, java.lang.Object>,java.lang.String,java.lang.String,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler)",
                "predicate": "{[/api/{repository}/search/{search}],methods=[GET],produces=[application/x-spring-data-compact+json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.data.rest.webmvc.RepositorySearchController.optionsForSearch(org.springframework.data.rest.webmvc.RootResourceInformation,java.lang.String)",
                "predicate": "{[/api/{repository}/search/{search}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.data.rest.webmvc.RepositorySearchController.headForSearch(org.springframework.data.rest.webmvc.RootResourceInformation,java.lang.String)",
                "predicate": "{[/api/{repository}/search/{search}],methods=[HEAD],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}/{propertyId}],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}],methods=[GET],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.deletePropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}],methods=[DELETE],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReferenceCompact(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.createPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.http.HttpMethod,org.springframework.hateoas.Resources<java.lang.Object>,java.io.Serializable,java.lang.String) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}],methods=[PATCH || PUT || POST],consumes=[application/json || application/x-spring-data-compact+json || text/uri-list],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.deletePropertyReferenceId(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,java.lang.String) throws java.lang.Exception",
                "predicate": "{[/api/{repository}/{id}/{property}/{propertyId}],methods=[DELETE],produces=[application/hal+json || application/json]}"
            },
            {
                "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@652dcdbd]]",
                "predicate": "/webjars/**"
            },
            {
                "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@3573cd19]]",
                "predicate": "/**"
            }
        ]
    },
    "servletFilters": [
        {
            "className": "org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter",
            "name": "requestContextFilter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        },
        {
            "className": "org.apache.tomcat.websocket.server.WsFilter",
            "name": "Tomcat WebSocket (JSR356) Filter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        },
        {
            "className": "org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter",
            "name": "httpPutFormContentFilter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        },
        {
            "className": "org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter",
            "name": "hiddenHttpMethodFilter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        },
        {
            "className": "org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter",
            "name": "characterEncodingFilter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        },
        {
            "className": "org.springframework.boot.actuate.trace.WebRequestTraceFilter",
            "name": "webRequestLoggingFilter",
            "servletNameMappings": [],
            "urlPatternMappings": [
                "/*"
            ]
        }
    ],
    "servlets": [
        {
            "className": "org.apache.catalina.servlets.DefaultServlet",
            "mappings": [],
            "name": "default"
        },
        {
            "className": "org.springframework.web.servlet.DispatcherServlet",
            "mappings": [
                "/"
            ],
            "name": "dispatcherServlet"
        }
    ]
}

And here's an example for a WebFlux application:

{
    "dispatcherHandlers": {
        "webHandler": [
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/autoconfig],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/status],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$WriteOperationHandler.handle(org.springframework.web.server.ServerWebExchange,java.util.Map<java.lang.String, java.lang.String>)",
                "predicate": "{[/application/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/trace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "public org.reactivestreams.Publisher<org.springframework.http.ResponseEntity<java.lang.Object>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping$ReadOperationHandler.handle(org.springframework.web.server.ServerWebExchange)",
                "predicate": "{[/application/heapdump],methods=[GET],produces=[application/octet-stream]}"
            },
            {
                "handler": "private java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping.links(org.springframework.http.server.reactive.ServerHttpRequest)",
                "predicate": "{[/application],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
            },
            {
                "handler": "sample.webflux.SampleWebFluxApplication$$Lambda$177/2063786038@49bd54f7",
                "predicate": "(POST && /echo)"
            },
            {
                "handler": "sample.webflux.SampleWebFluxApplication$$Lambda$179/1005093407@6b5f8707",
                "predicate": "(GET && /whatever)"
            },
            {
                "handler": "public java.lang.String sample.webflux.WelcomeController.welcome()",
                "predicate": "{[/],methods=[GET]}"
            },
            {
                "handler": "ResourceWebHandler [locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.reactive.resource.PathResourceResolver@3258b7d8]]",
                "predicate": "/webjars/**"
            },
            {
                "handler": "ResourceWebHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.reactive.resource.PathResourceResolver@6a38fa48]]",
                "predicate": "/**"
            }
        ]
    }
}

A few notes about the example responses:

  • dispatcherServlets and dispatcherHandlers are as there may be more than one DispatcherServlet or DispatcherHandler bean in the application context.
  • The keys in the dispatcherServlets and dispatcherHandlers maps are the names of the beans.
  • The values in the dispatcherServlets and dispatcherHandlers maps are arrays of the known handlers. The order of the array reflects the order of the handlers in the dispatcher.
  • The top-level keys (dispatcherServlets, dispatcherHandlers, servlets, servletFilters) are named such that they are unique even when a client might be dealing with a mixture of servlet and reactive web applications.
  • It would be nice to be able to list WebFilters used by WebFlux but that doesn't appear to be possible (at the moment at least) without resorting to reflective hacks.
  • The code that produced the above is in this branch of my fork.
kaleev

kaleev commented on Nov 2, 2017

@kaleev

Mapping endpoint's output contains endpoints entries (e.g beans, health) when management port is equal to application port, and it doesn’t contain them when management port differs from application port.
It seems like a bug. So it should be possible to distinguish management request mappings and application request mappings in json output, since IDEA as well as STS need to build correct URLs for entries from the output in order to get an ability to navigate to them.
I suppose top-level 'context' keys would be enough.

wilkinsona

wilkinsona commented on Nov 2, 2017

@wilkinsona
MemberAuthor

Thank you, @kaleev. Given that the change proposed here is going to be a breaking change to the JSON's structure, and fixing the problem you've described would also require a breaking change, doing both at the same time makes a lot of sense. I'll see what we can do.

wilkinsona

wilkinsona commented on Nov 2, 2017

@wilkinsona
MemberAuthor

The problem with the mappings not being visible when there's a context hierarchy (as there is when the management port is set) is a specific case of the problem tracked by #5312.

wilkinsona

wilkinsona commented on Nov 2, 2017

@wilkinsona
MemberAuthor

There's a problem with the proposed implementation when the management port has been configured. If a request to the mappings endpoint is made before the application's dispatcher servlet has handled any request, its handler mappings will be null as they are only initialized on first request by default. I've asked @rstoyanchev if there's anything that could be done in the Framework to remove this restriction.

removed this from the 2.0.0.M6 milestone on Nov 3, 2017

7 remaining items

self-assigned this
on Jan 4, 2018
removed
status: blockedAn issue that's blocked on an external project change
on Jan 12, 2018
wilkinsona

wilkinsona commented on Jan 16, 2018

@wilkinsona
MemberAuthor

The response structure has changed to align with the recent changes for better handling of context hierarchies. Here's an example of the updated structure:

{
    "contexts": {
        "application": {
            "mappings": {
                "dispatcherServlets": {
                    "dispatcherServlet": [
                        {
                            "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@282c6b8]]",
                            "predicate": "/**/favicon.ico"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)",
                            "predicate": "{[/error]}"
                        },
                        {
                            "handler": "public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)",
                            "predicate": "{[/error],produces=[text/html]}"
                        },
                        {
                            "handler": "org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.RootResourceInformation> org.springframework.data.rest.webmvc.alps.AlpsController.descriptor(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/profile/{repository}],methods=[GET],produces=[application/alps+json || */*]}"
                        },
                        {
                            "handler": "org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.alps.AlpsController.alpsOptions()",
                            "predicate": "{[/api/profile/{repository}],methods=[OPTIONS],produces=[application/alps+json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.json.JsonSchema> org.springframework.data.rest.webmvc.RepositorySchemaController.schema(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/profile/{repository}],methods=[GET],produces=[application/schema+json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.ProfileController.profileOptions()",
                            "predicate": "{[/api/profile],methods=[OPTIONS]}"
                        },
                        {
                            "handler": "org.springframework.http.HttpEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.ProfileController.listAllFormsOfMetadata()",
                            "predicate": "{[/api/profile],methods=[GET]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}/{propertyId}],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.deletePropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}],methods=[DELETE],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.followPropertyReferenceCompact(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.createPropertyReference(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.http.HttpMethod,org.springframework.hateoas.Resources<java.lang.Object>,java.io.Serializable,java.lang.String) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}],methods=[PATCH || PUT || POST],consumes=[application/json || application/x-spring-data-compact+json || text/uri-list],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.deletePropertyReferenceId(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,java.lang.String,java.lang.String) throws java.lang.Exception",
                            "predicate": "{[/api/{repository}/{id}/{property}/{propertyId}],methods=[DELETE],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositoryController.optionsForRepositories()",
                            "predicate": "{[/api/ || /api],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryController.headForRepositories()",
                            "predicate": "{[/api/ || /api],methods=[HEAD],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<org.springframework.data.rest.webmvc.RepositoryLinksResource> org.springframework.data.rest.webmvc.RepositoryController.listRepositories()",
                            "predicate": "{[/api/ || /api],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.optionsForCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/{repository}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.headCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}],methods=[HEAD],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.hateoas.Resources<?> org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.hateoas.Resources<?> org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResourceCompact(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}],methods=[POST],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.optionsForItemResource(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/{repository}/{id}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.headForItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}/{id}],methods=[HEAD],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.Resource<?>> org.springframework.data.rest.webmvc.RepositoryEntityController.getItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.http.HttpHeaders) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}/{id}],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<? extends org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.putItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.data.rest.webmvc.support.ETag,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}/{id}],methods=[PUT],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.patchItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,java.io.Serializable,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.data.rest.webmvc.support.ETag,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException,org.springframework.data.rest.webmvc.ResourceNotFoundException",
                            "predicate": "{[/api/{repository}/{id}],methods=[PATCH],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositoryEntityController.deleteItemResource(org.springframework.data.rest.webmvc.RootResourceInformation,java.io.Serializable,org.springframework.data.rest.webmvc.support.ETag) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException",
                            "predicate": "{[/api/{repository}/{id}],methods=[DELETE],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.data.rest.webmvc.RepositorySearchesResource org.springframework.data.rest.webmvc.RepositorySearchController.listSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/{repository}/search],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.optionsForSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/{repository}/search],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.HttpEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.headForSearches(org.springframework.data.rest.webmvc.RootResourceInformation)",
                            "predicate": "{[/api/{repository}/search],methods=[HEAD],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<?> org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.util.MultiValueMap<java.lang.String, java.lang.Object>,java.lang.String,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,org.springframework.http.HttpHeaders)",
                            "predicate": "{[/api/{repository}/search/{search}],methods=[GET],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.hateoas.ResourceSupport org.springframework.data.rest.webmvc.RepositorySearchController.executeSearchCompact(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.http.HttpHeaders,org.springframework.util.MultiValueMap<java.lang.String, java.lang.Object>,java.lang.String,java.lang.String,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler)",
                            "predicate": "{[/api/{repository}/search/{search}],methods=[GET],produces=[application/x-spring-data-compact+json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.data.rest.webmvc.RepositorySearchController.optionsForSearch(org.springframework.data.rest.webmvc.RootResourceInformation,java.lang.String)",
                            "predicate": "{[/api/{repository}/search/{search}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "public org.springframework.http.ResponseEntity<java.lang.Object> org.springframework.data.rest.webmvc.RepositorySearchController.headForSearch(org.springframework.data.rest.webmvc.RootResourceInformation,java.lang.String)",
                            "predicate": "{[/api/{repository}/search/{search}],methods=[HEAD],produces=[application/hal+json || application/json]}"
                        },
                        {
                            "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/webjars/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@72f56ddf]]",
                            "predicate": "/webjars/**"
                        },
                        {
                            "handler": "ResourceHttpRequestHandler [locations=[class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@6656c23f]]",
                            "predicate": "/**"
                        }
                    ]
                },
                "servletFilters": [
                    {
                        "className": "org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter",
                        "name": "requestContextFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.apache.tomcat.websocket.server.WsFilter",
                        "name": "Tomcat WebSocket (JSR356) Filter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter",
                        "name": "httpPutFormContentFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter",
                        "name": "hiddenHttpMethodFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter",
                        "name": "characterEncodingFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter",
                        "name": "webMetricsFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    },
                    {
                        "className": "org.springframework.boot.actuate.trace.WebRequestTraceFilter",
                        "name": "webRequestLoggingFilter",
                        "servletNameMappings": [],
                        "urlPatternMappings": [
                            "/*"
                        ]
                    }
                ],
                "servlets": [
                    {
                        "className": "org.apache.catalina.servlets.DefaultServlet",
                        "mappings": [],
                        "name": "default"
                    },
                    {
                        "className": "org.springframework.web.servlet.DispatcherServlet",
                        "mappings": [
                            "/"
                        ],
                        "name": "dispatcherServlet"
                    }
                ]
            },
            "parentId": null
        }
    }
}

contexts is a new top-level entry. This map contains an entry for each application context, keyed by id, that's known to the endpoint. Each entry for a specific context has two keys: parentId and mappings. parentId is the id of the parent context, if any. mappings is a map of the context's mappings with entries that use the same 4 possible keys as described above (dispatcherServlets, dispatcherHandlers, servlets, servletFilters).

wilkinsona

wilkinsona commented on Jan 22, 2018

@wilkinsona
MemberAuthor

The code would benefit from being in a mappings-specific package rather than the more general-purpose actuate.web package that it's currently in.

5 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @philwebb@wilkinsona@kaleev

      Issue actions

        Overhaul the mappings endpoint · Issue #9979 · spring-projects/spring-boot