Allow multiple endpoint PathMapper beans

Update `WebEndpointDiscoverer` and related classes to that multiple
`PathMapper` beans can be registered. Mappers are now tried in order
until one returns a non-null value.

Closes gh-14841
pull/14844/merge
Phillip Webb 6 years ago
parent bebfa76f55
commit 6b37d87497

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
import java.util.Collection;
import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointFilter;
import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
@ -45,17 +46,17 @@ public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
* @param applicationContext the source application context
* @param parameterValueMapper the parameter value mapper
* @param endpointMediaTypes the endpoint media types
* @param endpointPathMapper the endpoint path mapper
* @param endpointPathMappers the endpoint path mappers
* @param invokerAdvisors invoker advisors to apply
* @param filters filters to apply
*/
public CloudFoundryWebEndpointDiscoverer(ApplicationContext applicationContext,
ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes, PathMapper endpointPathMapper,
EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
Collection<OperationInvokerAdvisor> invokerAdvisors,
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
super(applicationContext, parameterValueMapper, endpointMediaTypes,
endpointPathMapper, invokerAdvisors, filters);
endpointPathMappers, invokerAdvisors, filters);
}
@Override

@ -33,7 +33,6 @@ import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
@ -95,9 +94,8 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
WebClient.Builder webClientBuilder,
ControllerEndpointsSupplier controllerEndpointsSupplier) {
CloudFoundryWebEndpointDiscoverer endpointDiscoverer = new CloudFoundryWebEndpointDiscoverer(
this.applicationContext, parameterMapper, endpointMediaTypes,
PathMapper.useEndpointId(), Collections.emptyList(),
Collections.emptyList());
this.applicationContext, parameterMapper, endpointMediaTypes, null,
Collections.emptyList(), Collections.emptyList());
CloudFoundrySecurityInterceptor securityInterceptor = getSecurityInterceptor(
webClientBuilder, this.applicationContext.getEnvironment());
Collection<ExposableWebEndpoint> webEndpoints = endpointDiscoverer.getEndpoints();

@ -32,7 +32,6 @@ import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.health.HealthEndpoint;
@ -99,9 +98,8 @@ public class CloudFoundryActuatorAutoConfiguration {
ServletEndpointsSupplier servletEndpointsSupplier,
ControllerEndpointsSupplier controllerEndpointsSupplier) {
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
this.applicationContext, parameterMapper, endpointMediaTypes,
PathMapper.useEndpointId(), Collections.emptyList(),
Collections.emptyList());
this.applicationContext, parameterMapper, endpointMediaTypes, null,
Collections.emptyList(), Collections.emptyList());
CloudFoundrySecurityInterceptor securityInterceptor = getSecurityInterceptor(
restTemplateBuilder, this.applicationContext.getEnvironment());
Collection<ExposableWebEndpoint> webEndpoints = discoverer.getEndpoints();

@ -21,6 +21,8 @@ import java.util.Map;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;
/**
@ -29,6 +31,7 @@ import org.springframework.util.StringUtils;
*
* @author Stephane Nicoll
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
class MappingWebEndpointPathMapper implements PathMapper {
private final Map<EndpointId, String> pathMapping;
@ -42,8 +45,7 @@ class MappingWebEndpointPathMapper implements PathMapper {
@Override
public String getRootPath(EndpointId endpointId) {
String path = this.pathMapping.get(endpointId);
return StringUtils.hasText(path) ? path
: PathMapper.useEndpointId().getRootPath(endpointId);
return StringUtils.hasText(path) ? path : null;
}
}

@ -80,7 +80,6 @@ public class WebEndpointAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean
public PathMapper webEndpointPathMapper() {
return new MappingWebEndpointPathMapper(this.properties.getPathMapping());
}
@ -95,11 +94,13 @@ public class WebEndpointAutoConfiguration {
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
public WebEndpointDiscoverer webEndpointDiscoverer(
ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes, PathMapper webEndpointPathMapper,
EndpointMediaTypes endpointMediaTypes,
ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
ObjectProvider<EndpointFilter<ExposableWebEndpoint>> filters) {
return new WebEndpointDiscoverer(this.applicationContext, parameterValueMapper,
endpointMediaTypes, webEndpointPathMapper,
endpointMediaTypes,
endpointPathMappers.orderedStream().collect(Collectors.toList()),
invokerAdvisors.orderedStream().collect(Collectors.toList()),
filters.orderedStream().collect(Collectors.toList()));
}
@ -107,10 +108,11 @@ public class WebEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ControllerEndpointsSupplier.class)
public ControllerEndpointDiscoverer controllerEndpointDiscoverer(
PathMapper webEndpointPathMapper,
ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<Collection<EndpointFilter<ExposableControllerEndpoint>>> filters) {
return new ControllerEndpointDiscoverer(this.applicationContext,
webEndpointPathMapper, filters.getIfAvailable(Collections::emptyList));
endpointPathMappers.orderedStream().collect(Collectors.toList()),
filters.getIfAvailable(Collections::emptyList));
}
@Bean
@ -144,10 +146,11 @@ public class WebEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ServletEndpointsSupplier.class)
public ServletEndpointDiscoverer servletEndpointDiscoverer(
ApplicationContext applicationContext, PathMapper webEndpointPathMapper,
ApplicationContext applicationContext,
ObjectProvider<PathMapper> endpointPathMappers,
ObjectProvider<EndpointFilter<ExposableServletEndpoint>> filters) {
return new ServletEndpointDiscoverer(applicationContext,
webEndpointPathMapper,
endpointPathMappers.orderedStream().collect(Collectors.toList()),
filters.orderedStream().collect(Collectors.toList()));
}

@ -95,7 +95,8 @@ public class CloudFoundryWebEndpointDiscovererTests {
Collections.singletonList("application/json"),
Collections.singletonList("application/json"));
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
context, parameterMapper, mediaTypes, endpointPathMapper,
context, parameterMapper, mediaTypes,
Collections.singletonList(endpointPathMapper),
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
Collections.emptyList());
consumer.accept(discoverer);

@ -36,7 +36,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
@ -220,8 +219,8 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
endpointMediaTypes, PathMapper.useEndpointId(),
Collections.emptyList(), Collections.emptyList());
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
}
@Bean

@ -36,7 +36,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
@ -219,8 +218,8 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
endpointMediaTypes, PathMapper.useEndpointId(),
Collections.emptyList(), Collections.emptyList());
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
}
@Bean

@ -21,6 +21,7 @@ import java.util.Collections;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import static org.assertj.core.api.Assertions.assertThat;
@ -35,29 +36,32 @@ public class MappingWebEndpointPathMapperTests {
public void defaultConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.emptyMap());
assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("test");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("test"))).isEqualTo("test");
}
@Test
public void userConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.singletonMap("test", "custom"));
assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("custom");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("test"))).isEqualTo("custom");
}
@Test
public void mixedCaseDefaultConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.emptyMap());
assertThat(mapper.getRootPath(EndpointId.of("testEndpoint")))
.isEqualTo("testEndpoint");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("testEndpoint"))).isEqualTo("testEndpoint");
}
@Test
public void mixedCaseUserConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.singletonMap("test-endpoint", "custom"));
assertThat(mapper.getRootPath(EndpointId.of("testEndpoint"))).isEqualTo("custom");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("testEndpoint"))).isEqualTo("custom");
}
}

@ -16,13 +16,21 @@
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer;
@ -30,6 +38,7 @@ import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDisco
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.stereotype.Component;
import static org.assertj.core.api.Assertions.assertThat;
@ -71,6 +80,27 @@ public class WebEndpointAutoConfigurationTests {
});
}
@Test
public void webApplicationSupportCustomPathMatcher() {
this.contextRunner
.withPropertyValues("management.endpoints.web.exposure.include=*",
"management.endpoints.web.path-mapping.testanotherone=foo")
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class,
TestAnotherOneEndpoint.class, TestTwoEndpoint.class)
.run((context) -> {
WebEndpointDiscoverer discoverer = context
.getBean(WebEndpointDiscoverer.class);
Collection<ExposableWebEndpoint> endpoints = discoverer
.getEndpoints();
ExposableWebEndpoint[] webEndpoints = endpoints
.toArray(new ExposableWebEndpoint[0]);
List<String> paths = Arrays.stream(webEndpoints)
.map(PathMappedEndpoint::getRootPath)
.collect(Collectors.toList());
assertThat(paths).containsOnly("1/testone", "foo", "testtwo");
});
}
@Test
public void webApplicationConfiguresEndpointDiscoverer() {
this.contextRunner.run((context) -> {
@ -100,4 +130,35 @@ public class WebEndpointAutoConfigurationTests {
.doesNotHaveBean(ServletEndpointDiscoverer.class));
}
@Component
private static class TestPathMatcher implements PathMapper {
@Override
public String getRootPath(EndpointId endpointId) {
if (endpointId.toString().endsWith("one")) {
return "1/" + endpointId.toString();
}
return null;
}
}
@Component
@Endpoint(id = "testone")
private static class TestOneEndpoint {
}
@Component
@Endpoint(id = "testanotherone")
private static class TestAnotherOneEndpoint {
}
@Component
@Endpoint(id = "testtwo")
private static class TestTwoEndpoint {
}
}

@ -26,7 +26,6 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpoi
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -102,8 +101,8 @@ public class JolokiaEndpointAutoConfigurationTests {
@Bean
public ServletEndpointDiscoverer servletEndpointDiscoverer(
ApplicationContext applicationContext) {
return new ServletEndpointDiscoverer(applicationContext,
PathMapper.useEndpointId(), Collections.emptyList());
return new ServletEndpointDiscoverer(applicationContext, null,
Collections.emptyList());
}
}

@ -16,7 +16,11 @@
package org.springframework.boot.actuate.endpoint.web;
import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Strategy interface used to provide a mapping between an endpoint ID and the root path
@ -30,18 +34,42 @@ import org.springframework.boot.actuate.endpoint.EndpointId;
public interface PathMapper {
/**
* Resolve the root path for the endpoint with the specified {@code endpointId}.
* Resolve the root path for the specified {@code endpointId}.
* @param endpointId the id of an endpoint
* @return the path of the endpoint
* @return the path of the endpoint or {@code null} if this mapper doesn't support the
* given endpoint ID
*/
String getRootPath(EndpointId endpointId);
/**
* Returns an {@link PathMapper} that uses the endpoint ID as the path.
* @return an {@link PathMapper} that uses the lowercase endpoint ID as the path
* @deprecated since 2.1.0 in favor of {@link #getRootPath(List, EndpointId)} with a
* {@code null} list
*/
@Deprecated
static PathMapper useEndpointId() {
return (id) -> id.toString();
}
/**
* Resolve the root path for the specified {@code endpointId} from the given path
* mappers. If no mapper matches then the ID itself is returned.
* @param pathMappers the path mappers (may be {@code null})
* @param endpointId the id of an endpoint
* @return the path of the endpoint
*/
static String getRootPath(List<PathMapper> pathMappers, EndpointId endpointId) {
Assert.notNull(endpointId, "EndpointId must not be null");
if (pathMappers != null) {
for (PathMapper mapper : pathMappers) {
String path = mapper.getRootPath(endpointId);
if (StringUtils.hasText(path)) {
return path;
}
}
}
return endpointId.toString();
}
}

@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointId;
@ -29,7 +30,6 @@ import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@ -43,21 +43,20 @@ public class ControllerEndpointDiscoverer
extends EndpointDiscoverer<ExposableControllerEndpoint, Operation>
implements ControllerEndpointsSupplier {
private final PathMapper endpointPathMapper;
private final List<PathMapper> endpointPathMappers;
/**
* Create a new {@link ControllerEndpointDiscoverer} instance.
* @param applicationContext the source application context
* @param endpointPathMapper the endpoint path mapper
* @param endpointPathMappers the endpoint path mappers
* @param filters filters to apply
*/
public ControllerEndpointDiscoverer(ApplicationContext applicationContext,
PathMapper endpointPathMapper,
List<PathMapper> endpointPathMappers,
Collection<EndpointFilter<ExposableControllerEndpoint>> filters) {
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
filters);
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
this.endpointPathMapper = endpointPathMapper;
this.endpointPathMappers = endpointPathMappers;
}
@Override
@ -70,7 +69,7 @@ public class ControllerEndpointDiscoverer
@Override
protected ExposableControllerEndpoint createEndpoint(Object endpointBean,
EndpointId id, boolean enabledByDefault, Collection<Operation> operations) {
String rootPath = this.endpointPathMapper.getRootPath(id);
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath,
enabledByDefault);
}

@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointId;
@ -30,7 +31,6 @@ import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@ -43,21 +43,20 @@ public class ServletEndpointDiscoverer
extends EndpointDiscoverer<ExposableServletEndpoint, Operation>
implements ServletEndpointsSupplier {
private final PathMapper endpointPathMapper;
private final List<PathMapper> endpointPathMappers;
/**
* Create a new {@link ServletEndpointDiscoverer} instance.
* @param applicationContext the source application context
* @param endpointPathMapper the endpoint path mapper
* @param endpointPathMappers the endpoint path mappers
* @param filters filters to apply
*/
public ServletEndpointDiscoverer(ApplicationContext applicationContext,
PathMapper endpointPathMapper,
List<PathMapper> endpointPathMappers,
Collection<EndpointFilter<ExposableServletEndpoint>> filters) {
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
filters);
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
this.endpointPathMapper = endpointPathMapper;
this.endpointPathMappers = endpointPathMappers;
}
@Override
@ -69,7 +68,7 @@ public class ServletEndpointDiscoverer
@Override
protected ExposableServletEndpoint createEndpoint(Object endpointBean, EndpointId id,
boolean enabledByDefault, Collection<Operation> operations) {
String rootPath = this.endpointPathMapper.getRootPath(id);
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath,
enabledByDefault);
}

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.endpoint.web.annotation;
import java.util.Collection;
import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointId;
@ -32,7 +33,6 @@ import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.WebOperation;
import org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
/**
* {@link EndpointDiscoverer} for {@link ExposableWebEndpoint web endpoints}.
@ -44,7 +44,7 @@ public class WebEndpointDiscoverer
extends EndpointDiscoverer<ExposableWebEndpoint, WebOperation>
implements WebEndpointsSupplier {
private final PathMapper endpointPathMapper;
private final List<PathMapper> endpointPathMappers;
private final RequestPredicateFactory requestPredicateFactory;
@ -53,25 +53,24 @@ public class WebEndpointDiscoverer
* @param applicationContext the source application context
* @param parameterValueMapper the parameter value mapper
* @param endpointMediaTypes the endpoint media types
* @param endpointPathMapper the endpoint path mapper
* @param endpointPathMappers the endpoint path mappers
* @param invokerAdvisors invoker advisors to apply
* @param filters filters to apply
*/
public WebEndpointDiscoverer(ApplicationContext applicationContext,
ParameterValueMapper parameterValueMapper,
EndpointMediaTypes endpointMediaTypes, PathMapper endpointPathMapper,
EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
Collection<OperationInvokerAdvisor> invokerAdvisors,
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
super(applicationContext, parameterValueMapper, invokerAdvisors, filters);
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
this.endpointPathMapper = endpointPathMapper;
this.endpointPathMappers = endpointPathMappers;
this.requestPredicateFactory = new RequestPredicateFactory(endpointMediaTypes);
}
@Override
protected ExposableWebEndpoint createEndpoint(Object endpointBean, EndpointId id,
boolean enabledByDefault, Collection<WebOperation> operations) {
String rootPath = this.endpointPathMapper.getRootPath(id);
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath,
enabledByDefault, operations);
}
@ -79,7 +78,7 @@ public class WebEndpointDiscoverer
@Override
protected WebOperation createOperation(EndpointId endpointId,
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
String rootPath = this.endpointPathMapper.getRootPath(endpointId);
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, endpointId);
WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory
.getRequestPredicate(endpointId, rootPath, operationMethod);
return new DiscoveredWebOperation(endpointId, operationMethod, invoker,

@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@ -68,7 +67,7 @@ class BaseConfiguration {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
endpointMediaTypes(), PathMapper.useEndpointId(), Collections.emptyList(),
endpointMediaTypes(), null, Collections.emptyList(),
Collections.emptyList());
}

@ -29,7 +29,6 @@ import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
@ -153,7 +152,7 @@ public class ControllerEndpointDiscovererTests {
Consumer<ControllerEndpointDiscoverer> consumer) {
return (context) -> {
ControllerEndpointDiscoverer discoverer = new ControllerEndpointDiscoverer(
context, PathMapper.useEndpointId(), Collections.emptyList());
context, null, Collections.emptyList());
consumer.accept(discoverer);
};
}

@ -38,7 +38,6 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.EndpointServlet;
import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
@ -152,7 +151,7 @@ public class ServletEndpointDiscovererTests {
Consumer<ServletEndpointDiscoverer> consumer) {
return (context) -> {
ServletEndpointDiscoverer discoverer = new ServletEndpointDiscoverer(context,
PathMapper.useEndpointId(), Collections.emptyList());
null, Collections.emptyList());
consumer.accept(discoverer);
};
}

@ -261,7 +261,8 @@ public class WebEndpointDiscovererTests {
Collections.singletonList("application/json"),
Collections.singletonList("application/json"));
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(context,
parameterMapper, mediaTypes, endpointPathMapper,
parameterMapper, mediaTypes,
Collections.singletonList(endpointPathMapper),
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
Collections.emptyList());
consumer.accept(discoverer);

@ -25,7 +25,6 @@ import java.util.function.Consumer;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
@ -128,8 +127,8 @@ public class ControllerEndpointHandlerMappingIntegrationTests {
@Bean
public ControllerEndpointDiscoverer webEndpointDiscoverer(
ApplicationContext applicationContext) {
return new ControllerEndpointDiscoverer(applicationContext,
PathMapper.useEndpointId(), Collections.emptyList());
return new ControllerEndpointDiscoverer(applicationContext, null,
Collections.emptyList());
}
@Bean

@ -25,7 +25,6 @@ import java.util.function.Consumer;
import org.junit.Test;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
@ -122,8 +121,8 @@ public class ControllerEndpointHandlerMappingIntegrationTests {
@Bean
public ControllerEndpointDiscoverer webEndpointDiscoverer(
ApplicationContext applicationContext) {
return new ControllerEndpointDiscoverer(applicationContext,
PathMapper.useEndpointId(), Collections.emptyList());
return new ControllerEndpointDiscoverer(applicationContext, null,
Collections.emptyList());
}
@Bean

@ -34,7 +34,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -102,8 +101,8 @@ class JerseyEndpointsRunner extends AbstractWebEndpointRunner {
mediaTypes);
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
this.applicationContext, new ConversionServiceParameterValueMapper(),
endpointMediaTypes, PathMapper.useEndpointId(),
Collections.emptyList(), Collections.emptyList());
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
Collection<Resource> resources = new JerseyEndpointResourceFactory()
.createEndpointResources(new EndpointMapping("/actuator"),
discoverer.getEndpoints(), endpointMediaTypes,

@ -28,7 +28,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -108,8 +107,8 @@ class WebFluxEndpointsRunner extends AbstractWebEndpointRunner {
mediaTypes);
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
this.applicationContext, new ConversionServiceParameterValueMapper(),
endpointMediaTypes, PathMapper.useEndpointId(),
Collections.emptyList(), Collections.emptyList());
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
return new WebFluxEndpointHandlerMapping(new EndpointMapping("/actuator"),
discoverer.getEndpoints(), endpointMediaTypes,
new CorsConfiguration(),

@ -28,7 +28,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@ -91,8 +90,8 @@ class WebMvcEndpointRunner extends AbstractWebEndpointRunner {
mediaTypes);
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
this.applicationContext, new ConversionServiceParameterValueMapper(),
endpointMediaTypes, PathMapper.useEndpointId(),
Collections.emptyList(), Collections.emptyList());
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
return new WebMvcEndpointHandlerMapping(new EndpointMapping("/actuator"),
discoverer.getEndpoints(), endpointMediaTypes,
new CorsConfiguration(),

Loading…
Cancel
Save