This commit is contained in:
Phillip Webb
2017-11-01 15:48:03 -07:00
parent 44d8e09aac
commit c55b5d7111
62 changed files with 237 additions and 229 deletions

View File

@@ -18,8 +18,7 @@ package org.springframework.boot.actuate.endpoint;
/**
* A {@code ParameterMappingException} is thrown when a failure occurs during
* {@link ParameterMapper#mapParameter(Object, Class) operation parameter
* mapping}.
* {@link ParameterMapper#mapParameter(Object, Class) operation parameter mapping}.
*
* @author Andy Wilkinson
* @since 2.0.0

View File

@@ -23,15 +23,14 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.DefaultFormattingConversionService;
/**
* {@link ParameterMapper} that uses a {@link ConversionService} to map parameter
* values if necessary.
* {@link ParameterMapper} that uses a {@link ConversionService} to map parameter values
* if necessary.
*
* @author Stephane Nicoll
* @author Phillip Webb
* @since 2.0.0
*/
public class ConversionServiceParameterMapper
implements ParameterMapper {
public class ConversionServiceParameterMapper implements ParameterMapper {
private final ConversionService conversionService;
@@ -43,8 +42,7 @@ public class ConversionServiceParameterMapper
* Create a new instance with the {@link ConversionService} to use.
* @param conversionService the conversion service
*/
public ConversionServiceParameterMapper(
ConversionService conversionService) {
public ConversionServiceParameterMapper(ConversionService conversionService) {
this.conversionService = new BinderConversionService(conversionService);
}

View File

@@ -115,8 +115,8 @@ public class JmxAnnotationEndpointDiscoverer
public JmxEndpointOperation createOperation(String endpointId,
AnnotationAttributes operationAttributes, Object target, Method method,
OperationType type, long timeToLive) {
ReflectiveOperationInvoker invoker = new ReflectiveOperationInvoker(
target, method, this.parameterMapper);
ReflectiveOperationInvoker invoker = new ReflectiveOperationInvoker(target,
method, this.parameterMapper);
String operationName = method.getName();
Class<?> outputType = getJmxType(method.getReturnType());
String description = getDescription(method,

View File

@@ -32,4 +32,12 @@ public interface EndpointPathResolver {
*/
String resolvePath(String endpointId);
/**
* Returns an {@link EndpointPathResolver} that uses the endpoint ID as the path.
* @return an {@link EndpointPathResolver} that uses the endpoint ID as the path
*/
static EndpointPathResolver useEndpointId() {
return (endpointId) -> endpointId;
}
}

View File

@@ -30,8 +30,8 @@ import org.reactivestreams.Publisher;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.ParameterMapper;
import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.ParameterMapper;
import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
@@ -67,8 +67,8 @@ public class WebAnnotationEndpointDiscoverer extends
* {@link Endpoint endpoints} and {@link WebEndpointExtension web extensions} using
* the given {@link ApplicationContext}.
* @param applicationContext the application context
* @param parameterMapper the {@link ParameterMapper} used to
* convert arguments when an operation is invoked
* @param parameterMapper the {@link ParameterMapper} used to convert arguments when
* an operation is invoked
* @param cachingConfigurationFactory the {@link CachingConfiguration} factory to use
* @param endpointMediaTypes the media types produced and consumed by web endpoint
* operations
@@ -81,8 +81,8 @@ public class WebAnnotationEndpointDiscoverer extends
EndpointMediaTypes endpointMediaTypes,
EndpointPathResolver endpointPathResolver) {
super(applicationContext,
new WebEndpointOperationFactory(parameterMapper,
endpointMediaTypes, endpointPathResolver),
new WebEndpointOperationFactory(parameterMapper, endpointMediaTypes,
endpointPathResolver),
WebEndpointOperation::getRequestPredicate, cachingConfigurationFactory);
}
@@ -145,8 +145,8 @@ public class WebAnnotationEndpointDiscoverer extends
determineConsumedMediaTypes(httpMethod, method),
determineProducedMediaTypes(
operationAttributes.getStringArray("produces"), method));
OperationInvoker invoker = new ReflectiveOperationInvoker(
target, method, this.parameterMapper);
OperationInvoker invoker = new ReflectiveOperationInvoker(target, method,
this.parameterMapper);
if (timeToLive > 0) {
invoker = new CachingOperationInvoker(invoker, timeToLive);
}

View File

@@ -31,8 +31,7 @@ public abstract class AbstractReactiveHealthIndicator implements ReactiveHealthI
@Override
public final Mono<Health> health() {
try {
return doHealthCheck(new Health.Builder())
.onErrorResume(this::handleFailure);
return doHealthCheck(new Health.Builder()).onErrorResume(this::handleFailure);
}
catch (Exception ex) {
return handleFailure(ex);

View File

@@ -385,7 +385,7 @@ public abstract class AbstractWebEndpointIntegrationTests<T extends Configurable
DefaultConversionService.getSharedInstance());
return new WebAnnotationEndpointDiscoverer(applicationContext,
parameterMapper, (id) -> new CachingConfiguration(0),
endpointMediaTypes(), (id) -> id);
endpointMediaTypes(), EndpointPathResolver.useEndpointId());
}
@Bean

View File

@@ -240,17 +240,18 @@ public class WebAnnotationEndpointDiscovererTests {
@Test
public void endpointPathCanBeCustomized() {
load((id) -> null, (id) -> "custom/" + id,
AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
Map<String, EndpointInfo<WebEndpointOperation>> endpoints = mapEndpoints(
discoverer.discoverEndpoints());
assertThat(endpoints).containsOnlyKeys("test");
EndpointInfo<WebEndpointOperation> endpoint = endpoints.get("test");
assertThat(requestPredicates(endpoint)).has(requestPredicates(
path("custom/test").httpMethod(WebEndpointHttpMethod.GET).consumes()
.produces("application/json"),
path("custom/test/{id}").httpMethod(WebEndpointHttpMethod.GET).consumes()
.produces("application/json")));
});
AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
Map<String, EndpointInfo<WebEndpointOperation>> endpoints = mapEndpoints(
discoverer.discoverEndpoints());
assertThat(endpoints).containsOnlyKeys("test");
EndpointInfo<WebEndpointOperation> endpoint = endpoints.get("test");
Condition<List<? extends OperationRequestPredicate>> expected = requestPredicates(
path("custom/test").httpMethod(WebEndpointHttpMethod.GET)
.consumes().produces("application/json"),
path("custom/test/{id}").httpMethod(WebEndpointHttpMethod.GET)
.consumes().produces("application/json"));
assertThat(requestPredicates(endpoint)).has(expected);
});
}
private void load(Class<?> configuration,
@@ -259,20 +260,18 @@ public class WebAnnotationEndpointDiscovererTests {
}
private void load(CachingConfigurationFactory cachingConfigurationFactory,
EndpointPathResolver endpointPathResolver,
Class<?> configuration, Consumer<WebAnnotationEndpointDiscoverer> consumer) {
EndpointPathResolver endpointPathResolver, Class<?> configuration,
Consumer<WebAnnotationEndpointDiscoverer> consumer) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
configuration);
try {
consumer.accept(
new WebAnnotationEndpointDiscoverer(context,
new ConversionServiceParameterMapper(
DefaultConversionService.getSharedInstance()),
cachingConfigurationFactory,
new EndpointMediaTypes(
Collections.singletonList("application/json"),
Collections.singletonList("application/json")),
endpointPathResolver));
consumer.accept(new WebAnnotationEndpointDiscoverer(context,
new ConversionServiceParameterMapper(
DefaultConversionService.getSharedInstance()),
cachingConfigurationFactory,
new EndpointMediaTypes(Collections.singletonList("application/json"),
Collections.singletonList("application/json")),
endpointPathResolver));
}
finally {
context.close();

View File

@@ -31,6 +31,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@@ -97,9 +98,9 @@ class JerseyEndpointsRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext,
new ConversionServiceParameterMapper(), (id) -> null,
endpointMediaTypes, (id) -> id);
this.applicationContext, new ConversionServiceParameterMapper(),
(id) -> null, endpointMediaTypes,
EndpointPathResolver.useEndpointId());
Collection<Resource> resources = new JerseyEndpointResourceFactory()
.createEndpointResources(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes);

View File

@@ -25,6 +25,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@@ -103,9 +104,9 @@ class WebFluxEndpointsRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext,
new ConversionServiceParameterMapper(), (id) -> null,
endpointMediaTypes, (id) -> id);
this.applicationContext, new ConversionServiceParameterMapper(),
(id) -> null, endpointMediaTypes,
EndpointPathResolver.useEndpointId());
return new WebFluxEndpointHandlerMapping(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes,
new CorsConfiguration());

View File

@@ -25,6 +25,7 @@ import org.junit.runners.model.InitializationError;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.EndpointPathResolver;
import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@@ -86,9 +87,9 @@ class WebMvcEndpointRunner extends AbstractWebEndpointRunner {
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes,
mediaTypes);
WebAnnotationEndpointDiscoverer discoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext,
new ConversionServiceParameterMapper(), (id) -> null,
endpointMediaTypes, (id) -> id);
this.applicationContext, new ConversionServiceParameterMapper(),
(id) -> null, endpointMediaTypes,
EndpointPathResolver.useEndpointId());
return new WebMvcEndpointHandlerMapping(new EndpointMapping("/application"),
discoverer.discoverEndpoints(), endpointMediaTypes,
new CorsConfiguration());