Extract MVC concerns completely from Endpoint implementations
This commit is contained in:
parent
71ebcbff3e
commit
87e00cfae9
|
|
@ -17,6 +17,8 @@
|
|||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
|
@ -28,8 +30,19 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.GenericMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
|
@ -50,6 +63,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
|
@ -119,6 +133,50 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
};
|
||||
}
|
||||
|
||||
@Component
|
||||
protected static class GenericEndpointPostProcessor implements
|
||||
BeanDefinitionRegistryPostProcessor {
|
||||
|
||||
private BeanDefinitionRegistry registry;
|
||||
|
||||
private Map<Class<? extends Endpoint<?>>, Class<?>> endpointTypes = new HashMap<Class<? extends Endpoint<?>>, Class<?>>();
|
||||
|
||||
public GenericEndpointPostProcessor() {
|
||||
this.endpointTypes.put(EnvironmentEndpoint.class,
|
||||
EnvironmentMvcEndpoint.class);
|
||||
this.endpointTypes.put(MetricsEndpoint.class, MetricsMvcEndpoint.class);
|
||||
this.endpointTypes.put(ShutdownEndpoint.class, ShutdownMvcEndpoint.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
for (String name : beanFactory.getBeanNamesForType(Endpoint.class)) {
|
||||
Class<?> type = getTypeForEndpoint(beanFactory.getType(name));
|
||||
BeanDefinitionBuilder bean = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(type);
|
||||
bean.addConstructorArgReference(name);
|
||||
this.registry.registerBeanDefinition("mvc." + name,
|
||||
bean.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getTypeForEndpoint(Class<?> endpoint) {
|
||||
Class<?> type = GenericMvcEndpoint.class;
|
||||
if (this.endpointTypes.containsKey(endpoint)) {
|
||||
type = this.endpointTypes.get(endpoint);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||
throws BeansException {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
|
||||
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
|
|
|
|||
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.config.JsonParser;
|
||||
import org.springframework.boot.config.JsonParserFactory;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.support.LiveBeansView;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Exposes JSON view of Spring beans. If the {@link Environment} contains a key setting
|
||||
|
|
@ -36,12 +36,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.beans", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class BeansEndpoint extends AbstractEndpoint<String> implements
|
||||
public class BeansEndpoint extends AbstractEndpoint<List<Object>> implements
|
||||
ApplicationContextAware {
|
||||
|
||||
private LiveBeansView liveBeansView = new LiveBeansView();
|
||||
|
||||
private JsonParser parser = JsonParserFactory.getJsonParser();
|
||||
|
||||
public BeansEndpoint() {
|
||||
super("/beans");
|
||||
}
|
||||
|
|
@ -55,9 +56,7 @@ public class BeansEndpoint extends AbstractEndpoint<String> implements
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public String invoke() {
|
||||
return this.liveBeansView.getSnapshotAsJson();
|
||||
public List<Object> invoke() {
|
||||
return this.parser.parseList(this.liveBeansView.getSnapshotAsJson());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,10 @@ package org.springframework.boot.actuate.endpoint;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
|
@ -41,7 +38,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
* @author Christian Dupuis
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.configprops", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class ConfigurationPropertiesReportEndpoint extends
|
||||
AbstractEndpoint<Map<String, Object>> implements ApplicationContextAware {
|
||||
|
||||
|
|
@ -67,8 +63,7 @@ public class ConfigurationPropertiesReportEndpoint extends
|
|||
this.keysToSanitize = keysToSanitize;
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> beans = extract(this.context);
|
||||
return beans;
|
||||
|
|
|
|||
|
|
@ -21,10 +21,7 @@ import java.lang.management.ThreadInfo;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose thread info.
|
||||
|
|
@ -32,7 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.dump", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class DumpEndpoint extends AbstractEndpoint<List<ThreadInfo>> {
|
||||
|
||||
/**
|
||||
|
|
@ -43,8 +39,6 @@ public class DumpEndpoint extends AbstractEndpoint<List<ThreadInfo>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public List<ThreadInfo> invoke() {
|
||||
return Arrays.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true,
|
||||
true));
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.springframework.boot.actuate.endpoint;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
|
@ -27,11 +26,6 @@ import org.springframework.core.env.EnumerablePropertySource;
|
|||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link ConfigurableEnvironment environment} information.
|
||||
|
|
@ -40,7 +34,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
|||
* @author Phillip Webb
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.env", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
EnvironmentAware {
|
||||
|
||||
|
|
@ -54,8 +47,6 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> i
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
result.put("profiles", this.environment.getActiveProfiles());
|
||||
|
|
@ -72,16 +63,6 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> i
|
|||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
String result = this.environment.getProperty(name);
|
||||
if (result == null) {
|
||||
throw new NoSuchPropertyException("No such property: " + name);
|
||||
}
|
||||
return sanitize(name, result);
|
||||
}
|
||||
|
||||
private Iterable<PropertySource<?>> getPropertySources() {
|
||||
if (this.environment != null
|
||||
&& this.environment instanceof ConfigurableEnvironment) {
|
||||
|
|
@ -90,7 +71,7 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> i
|
|||
return new StandardEnvironment().getPropertySources();
|
||||
}
|
||||
|
||||
private Object sanitize(String name, Object object) {
|
||||
public static Object sanitize(String name, Object object) {
|
||||
if (name.toLowerCase().endsWith("password")
|
||||
|| name.toLowerCase().endsWith("secret")) {
|
||||
return object == null ? null : "******";
|
||||
|
|
@ -103,13 +84,4 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> i
|
|||
this.environment = environment;
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such property")
|
||||
public static class NoSuchPropertyException extends RuntimeException {
|
||||
|
||||
public NoSuchPropertyException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,9 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose application health.
|
||||
|
|
@ -29,7 +26,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.health", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class HealthEndpoint<T> extends AbstractEndpoint<T> {
|
||||
|
||||
private HealthIndicator<? extends T> indicator;
|
||||
|
|
@ -50,8 +46,6 @@ public class HealthEndpoint<T> extends AbstractEndpoint<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public T invoke() {
|
||||
return this.indicator.health();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,8 @@ import java.util.Collections;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose arbitrary application information.
|
||||
|
|
@ -32,7 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.info", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private Map<String, ? extends Object> info;
|
||||
|
|
@ -49,8 +45,6 @@ public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(this.info);
|
||||
info.putAll(getAdditionalInfo());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
|
@ -33,22 +34,27 @@ import org.springframework.web.context.request.RequestContextHolder;
|
|||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
@ConfigurationProperties(name = "error")
|
||||
public class ManagementErrorEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
@FrameworkEndpoint
|
||||
public class ManagementErrorEndpoint implements MvcEndpoint {
|
||||
|
||||
private final ErrorController controller;
|
||||
private String path;
|
||||
|
||||
public ManagementErrorEndpoint(String path, ErrorController controller) {
|
||||
super(path, false, true);
|
||||
this.path = path;
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
|
||||
return this.controller.extract(attributes, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,15 +19,9 @@ package org.springframework.boot.actuate.endpoint;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.metrics.Metric;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link PublicMetrics}.
|
||||
|
|
@ -35,7 +29,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.metrics", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private PublicMetrics metrics;
|
||||
|
|
@ -52,8 +45,6 @@ public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (Metric metric : this.metrics.metrics()) {
|
||||
|
|
@ -62,22 +53,4 @@ public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
|||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
Object value = invoke().get(name);
|
||||
if (value == null) {
|
||||
throw new NoSuchMetricException("No such metric: " + name);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such metric")
|
||||
public static class NoSuchMetricException extends RuntimeException {
|
||||
|
||||
public NoSuchMetricException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,14 +20,10 @@ import java.util.Collections;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to shutdown the {@link ApplicationContext}.
|
||||
|
|
@ -36,7 +32,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Christian Dupuis
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||
ApplicationContextAware {
|
||||
|
||||
|
|
@ -50,8 +45,6 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
|
||||
if (this.context == null) {
|
||||
|
|
@ -59,21 +52,26 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> impl
|
|||
"No context to shutdown.");
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(500L);
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
// Swallow exception and continue
|
||||
}
|
||||
ShutdownEndpoint.this.context.close();
|
||||
}
|
||||
}).start();
|
||||
try {
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutting down, bye...");
|
||||
}
|
||||
finally {
|
||||
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"Shutting down, bye...");
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(500L);
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
// Swallow exception and continue
|
||||
}
|
||||
ShutdownEndpoint.this.context.close();
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -18,13 +18,10 @@ package org.springframework.boot.actuate.endpoint;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.trace.Trace;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose {@link Trace} information.
|
||||
|
|
@ -32,7 +29,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.trace", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class TraceEndpoint extends AbstractEndpoint<List<Trace>> {
|
||||
|
||||
private TraceRepository repository;
|
||||
|
|
@ -49,8 +45,6 @@ public class TraceEndpoint extends AbstractEndpoint<List<Trace>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public List<Trace> invoke() {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
if (bean instanceof String) {
|
||||
bean = getApplicationContext().getBean((String) handler);
|
||||
}
|
||||
if (bean instanceof Endpoint) {
|
||||
Endpoint<?> endpoint = (Endpoint<?>) bean;
|
||||
if (bean instanceof MvcEndpoint) {
|
||||
MvcEndpoint endpoint = (MvcEndpoint) bean;
|
||||
path = endpoint.getPath();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class EnvironmentMvcEndpoint extends GenericMvcEndpoint implements
|
||||
EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
public EnvironmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
String result = this.environment.getProperty(name);
|
||||
if (result == null) {
|
||||
throw new NoSuchPropertyException("No such property: " + name);
|
||||
}
|
||||
return EnvironmentEndpoint.sanitize(name, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such property")
|
||||
public static class NoSuchPropertyException extends RuntimeException {
|
||||
|
||||
public NoSuchPropertyException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class GenericMvcEndpoint implements MvcEndpoint {
|
||||
|
||||
private Endpoint<?> delegate;
|
||||
|
||||
public GenericMvcEndpoint(Endpoint<?> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Object invoke() {
|
||||
return this.delegate.invoke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.delegate.getPath();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class MetricsMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
private MetricsEndpoint delegate;
|
||||
|
||||
public MetricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||
super(delegate);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
Object value = this.delegate.invoke().get(name);
|
||||
if (value == null) {
|
||||
throw new NoSuchMetricException("No such metric: " + name);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such metric")
|
||||
public static class NoSuchMetricException extends RuntimeException {
|
||||
|
||||
public NoSuchMetricException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface MvcEndpoint {
|
||||
|
||||
String getPath();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class ShutdownMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public ShutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
@Override
|
||||
public Object invoke() {
|
||||
return super.invoke();
|
||||
}
|
||||
}
|
||||
|
|
@ -16,13 +16,16 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link BeansEndpoint}.
|
||||
|
|
@ -37,7 +40,9 @@ public class BeansEndpointTests extends AbstractEndpointTests<BeansEndpoint> {
|
|||
|
||||
@Test
|
||||
public void invoke() throws Exception {
|
||||
assertThat(getEndpointBean().invoke(), containsString("\"bean\": \"endpoint\""));
|
||||
List<Object> result = getEndpointBean().invoke();
|
||||
assertEquals(1, result.size());
|
||||
assertTrue(result.get(0) instanceof Map);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@ public class EndpointHandlerMappingTests {
|
|||
this.context.getDefaultListableBeanFactory().registerSingleton("mapping",
|
||||
this.mapping);
|
||||
this.mapping.setApplicationContext(this.context);
|
||||
this.method = ReflectionUtils.findMethod(TestEndpoint.class, "invoke");
|
||||
this.method = ReflectionUtils.findMethod(TestMvcEndpoint.class, "invoke");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withoutPrefix() throws Exception {
|
||||
TestEndpoint endpointA = new TestEndpoint("/a");
|
||||
TestEndpoint endpointB = new TestEndpoint("/b");
|
||||
TestMvcEndpoint endpointA = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
TestMvcEndpoint endpointB = new TestMvcEndpoint(new TestEndpoint("/b"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointA.getPath(), endpointA);
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
|
|
@ -76,8 +76,8 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
@Test
|
||||
public void withPrefix() throws Exception {
|
||||
TestEndpoint endpointA = new TestEndpoint("/a");
|
||||
TestEndpoint endpointB = new TestEndpoint("/b");
|
||||
TestMvcEndpoint endpointA = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
TestMvcEndpoint endpointB = new TestMvcEndpoint(new TestEndpoint("/b"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointA.getPath(), endpointA);
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
|
|
@ -96,7 +96,7 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyGetHttpMethodForNonActionEndpoints() throws Exception {
|
||||
TestEndpoint endpoint = new TestEndpoint("/a");
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
|
|
@ -106,7 +106,7 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
@Test
|
||||
public void postHttpMethodForActionEndpoints() throws Exception {
|
||||
TestEndpoint endpoint = new TestActionEndpoint("/a");
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
|
|
@ -115,7 +115,7 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyPostHttpMethodForActionEndpoints() throws Exception {
|
||||
TestEndpoint endpoint = new TestActionEndpoint("/a");
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
|
|
@ -125,7 +125,7 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
@Test
|
||||
public void disabled() throws Exception {
|
||||
TestEndpoint endpoint = new TestEndpoint("/a");
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.setDisabled(true);
|
||||
|
|
@ -134,7 +134,6 @@ public class EndpointHandlerMappingTests {
|
|||
nullValue());
|
||||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
private static class TestEndpoint extends AbstractEndpoint<Object> {
|
||||
|
||||
public TestEndpoint(String path) {
|
||||
|
|
@ -150,10 +149,19 @@ public class EndpointHandlerMappingTests {
|
|||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
private static class TestActionEndpoint extends TestEndpoint {
|
||||
private static class TestMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public TestActionEndpoint(String path) {
|
||||
super(path);
|
||||
public TestMvcEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
private static class TestActionEndpoint extends TestMvcEndpoint {
|
||||
|
||||
public TestActionEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue