Merge branch 'framework-endpoint'
This commit is contained in:
@@ -47,7 +47,6 @@ import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationReport;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.bind.PropertiesConfigurationFactory;
|
||||
@@ -57,7 +56,6 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for common management
|
||||
@@ -68,7 +66,6 @@ import org.springframework.http.MediaType;
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(MediaType.class)
|
||||
public class EndpointAutoConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
|
||||
@@ -29,18 +29,24 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
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.MetricsMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
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;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
@@ -85,21 +91,13 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerMapping endpointHandlerMapping() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(mvcEndpoints()
|
||||
.getEndpoints());
|
||||
mapping.setDisabled(ManagementServerPort.get(this.applicationContext) != ManagementServerPort.SAME);
|
||||
mapping.setPrefix(this.managementServerProperties.getContextPath());
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerAdapter endpointHandlerAdapter(
|
||||
final HttpMessageConverters messageConverters) {
|
||||
EndpointHandlerAdapter adapter = new EndpointHandlerAdapter();
|
||||
adapter.setMessageConverters(messageConverters.getConverters());
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
@@ -130,6 +128,30 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MvcEndpoints mvcEndpoints() {
|
||||
return new MvcEndpoints();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(EnvironmentEndpoint.class)
|
||||
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||
return new EnvironmentMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(MetricsEndpoint.class)
|
||||
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||
return new MetricsMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(ShutdownEndpoint.class)
|
||||
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
return new ShutdownMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
|
||||
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
@@ -26,15 +27,16 @@ import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerAdapter;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ManagementErrorEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
@@ -42,11 +44,10 @@ import org.springframework.boot.context.embedded.ErrorPage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
/**
|
||||
* Configuration triggered from {@link EndpointWebMvcAutoConfiguration} when a new
|
||||
@@ -57,6 +58,9 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||
@Configuration
|
||||
public class EndpointWebMvcChildContextConfiguration {
|
||||
|
||||
@Value("${error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Configuration
|
||||
protected static class ServerCustomization implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
@@ -100,13 +104,22 @@ public class EndpointWebMvcChildContextConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerMapping handlerMapping() {
|
||||
return new EndpointHandlerMapping();
|
||||
public HandlerAdapter handlerAdapter(HttpMessageConverters converters) {
|
||||
// TODO: maybe this needs more configuration for non-basic response use cases
|
||||
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
|
||||
adapter.setMessageConverters(converters.getConverters());
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerAdapter handlerAdapter() {
|
||||
return new EndpointHandlerAdapter();
|
||||
public HandlerMapping handlerMapping(MvcEndpoints endpoints,
|
||||
ListableBeanFactory beanFactory) {
|
||||
Set<MvcEndpoint> set = new HashSet<MvcEndpoint>(endpoints.getEndpoints());
|
||||
set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values());
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(set);
|
||||
// In a child context we definitely want to see the parent endpoints
|
||||
mapping.setDetectHandlerMethodsInAncestorContexts(true);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -116,15 +129,8 @@ public class EndpointWebMvcChildContextConfiguration {
|
||||
* endpoints.
|
||||
*/
|
||||
@Bean
|
||||
public Endpoint<Map<String, Object>> errorEndpoint(final ErrorController controller) {
|
||||
return new AbstractEndpoint<Map<String, Object>>("/error", false, true) {
|
||||
@Override
|
||||
protected Map<String, Object> doInvoke() {
|
||||
RequestAttributes attributes = RequestContextHolder
|
||||
.currentRequestAttributes();
|
||||
return controller.extract(attributes, false);
|
||||
}
|
||||
};
|
||||
public ManagementErrorEndpoint errorEndpoint(final ErrorController controller) {
|
||||
return new ManagementErrorEndpoint(this.errorPath, controller);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.util.Map;
|
||||
|
||||
import org.jolokia.http.AgentServlet;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.JolokiaEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@@ -65,6 +66,9 @@ public class JolokiaAutoConfiguration {
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Autowired
|
||||
private ManagementServerProperties management;
|
||||
|
||||
@Autowired
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment);
|
||||
@@ -77,19 +81,17 @@ public class JolokiaAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean()
|
||||
public ServletRegistrationBean jolokiaServletRegistration() {
|
||||
ServletRegistrationBean registrationBean = new ServletRegistrationBean(
|
||||
jolokiaServlet(), this.environment.getProperty("endpoints.jolokia.path",
|
||||
"/jolokia") + "/*");
|
||||
public ServletRegistrationBean jolokiaServletRegistration(AgentServlet servlet) {
|
||||
ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet,
|
||||
this.management.getContextPath() + jolokiaEndpoint().getPath() + "/*");
|
||||
addInitParameters(registrationBean);
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public JolokiaEndpoint jolokiaEndpoint() {
|
||||
return new JolokiaEndpoint();
|
||||
public JolokiaMvcEndpoint jolokiaEndpoint() {
|
||||
return new JolokiaMvcEndpoint();
|
||||
}
|
||||
|
||||
protected void addInitParameters(ServletRegistrationBean registrationBean) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.Filter;
|
||||
@@ -26,6 +27,7 @@ import javax.servlet.Filter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
@@ -210,9 +212,9 @@ public class ManagementSecurityAutoConfiguration {
|
||||
return NO_PATHS;
|
||||
}
|
||||
|
||||
List<Endpoint<?>> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
Set<? extends MvcEndpoint> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||
for (Endpoint<?> endpoint : endpoints) {
|
||||
for (MvcEndpoint endpoint : endpoints) {
|
||||
if (endpoint.isSensitive() == secure) {
|
||||
paths.add(endpoint.getPath());
|
||||
}
|
||||
|
||||
@@ -19,46 +19,42 @@ package org.springframework.boot.actuate.endpoint;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Abstract base for {@link Endpoint} implementations.
|
||||
* <p>
|
||||
* {@link Endpoint}s that support other {@link HttpMethod}s than {@link HttpMethod#GET}
|
||||
* should override {@link #methods()} and provide a list of supported methods.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||
|
||||
private static final MediaType[] NO_MEDIA_TYPES = new MediaType[0];
|
||||
|
||||
protected static final HttpMethod[] NO_HTTP_METHOD = new HttpMethod[0];
|
||||
|
||||
protected static final HttpMethod[] GET_HTTP_METHOD = new HttpMethod[] { HttpMethod.GET };
|
||||
|
||||
protected static final HttpMethod[] POST_HTTP_METHOD = new HttpMethod[] { HttpMethod.POST };
|
||||
|
||||
@NotNull
|
||||
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
||||
private String path;
|
||||
@Pattern(regexp = "\\w+", message = "ID must only contains letters, numbers and '_'")
|
||||
private String id;
|
||||
|
||||
private boolean sensitive;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
public AbstractEndpoint(String path) {
|
||||
this(path, true, true);
|
||||
public AbstractEndpoint(String id) {
|
||||
this(id, true, true);
|
||||
}
|
||||
|
||||
public AbstractEndpoint(String path, boolean sensitive, boolean enabled) {
|
||||
this.path = path;
|
||||
public AbstractEndpoint(String id, boolean sensitive, boolean enabled) {
|
||||
this.id = id;
|
||||
this.sensitive = sensitive;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@@ -67,15 +63,6 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
@@ -85,23 +72,4 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] produces() {
|
||||
return NO_MEDIA_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod[] methods() {
|
||||
return GET_HTTP_METHOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T invoke() {
|
||||
if (this.enabled) {
|
||||
return doInvoke();
|
||||
}
|
||||
throw new EndpointDisabledException();
|
||||
}
|
||||
|
||||
protected abstract T doInvoke();
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ public class AutoConfigurationReportEndpoint extends AbstractEndpoint<Report> {
|
||||
private AutoConfigurationReport autoConfigurationReport;
|
||||
|
||||
public AutoConfigurationReportEndpoint() {
|
||||
super("/autoconfig");
|
||||
super("autoconfig");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Report doInvoke() {
|
||||
public Report invoke() {
|
||||
return new Report(this.autoConfigurationReport);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Exposes JSON view of Spring beans. If the {@link Environment} contains a key setting
|
||||
@@ -33,13 +36,15 @@ import org.springframework.http.MediaType;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.beans", ignoreUnknownFields = false)
|
||||
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");
|
||||
super("beans");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,12 +56,7 @@ public class BeansEndpoint extends AbstractEndpoint<String> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType[] produces() {
|
||||
return new MediaType[] { MediaType.APPLICATION_JSON };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInvoke() {
|
||||
return this.liveBeansView.getSnapshotAsJson();
|
||||
public List<Object> invoke() {
|
||||
return this.parser.parseList(this.liveBeansView.getSnapshotAsJson());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* annotated classes.
|
||||
*
|
||||
* <p>
|
||||
* To protect sensitive information from being exposed, configure property names by using
|
||||
* <code>endpoints.configprops.keys_to_sanitize</code>.
|
||||
* To protect sensitive information from being exposed, certain property values are masked
|
||||
* if their names end with a set of configurable values (default "password" and "secret").
|
||||
* Configure property names by using {@link #setKeysToSanitize(String[])}.
|
||||
*
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
@@ -45,7 +46,7 @@ public class ConfigurationPropertiesReportEndpoint extends
|
||||
private ApplicationContext context;
|
||||
|
||||
public ConfigurationPropertiesReportEndpoint() {
|
||||
super("/configprops");
|
||||
super("configprops");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,9 +64,15 @@ public class ConfigurationPropertiesReportEndpoint extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> beans = extract(this.context);
|
||||
return beans;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<String, Object> doInvoke() {
|
||||
Map<String, Object> beans = this.context
|
||||
private Map<String, Object> extract(ApplicationContext context) {
|
||||
|
||||
Map<String, Object> beans = context
|
||||
.getBeansWithAnnotation(ConfigurationProperties.class);
|
||||
|
||||
// Serialize beans into map structure and sanitize values
|
||||
@@ -75,6 +82,10 @@ public class ConfigurationPropertiesReportEndpoint extends
|
||||
beans.put(entry.getKey(), sanitize(value));
|
||||
}
|
||||
|
||||
if (context.getParent() != null) {
|
||||
beans.put("parent", extract(context.getParent()));
|
||||
}
|
||||
|
||||
return beans;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ public class DumpEndpoint extends AbstractEndpoint<List<ThreadInfo>> {
|
||||
* Create a new {@link DumpEndpoint} instance.
|
||||
*/
|
||||
public DumpEndpoint() {
|
||||
super("/dump");
|
||||
super("dump");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ThreadInfo> doInvoke() {
|
||||
public List<ThreadInfo> invoke() {
|
||||
return Arrays.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true,
|
||||
true));
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* An endpoint that can be used to expose useful information to operations. Usually
|
||||
* exposed via Spring MVC but could also be exposed using some other technique.
|
||||
@@ -30,27 +27,22 @@ import org.springframework.http.MediaType;
|
||||
public interface Endpoint<T> {
|
||||
|
||||
/**
|
||||
* Returns the path of the endpoint. Must start with '/' and should not include
|
||||
* wildcards.
|
||||
* The logical ID of the endpoint. Must only contain simple letters, numbers and '_'
|
||||
* characters (ie a {@literal "\w"} regex).
|
||||
*/
|
||||
String getPath();
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns if the endpoint is sensitive, i.e. may return data that the average user
|
||||
* Return if the endpoint is enabled.
|
||||
*/
|
||||
boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Return if the endpoint is sensitive, i.e. may return data that the average user
|
||||
* should not see. Mappings can use this as a security hint.
|
||||
*/
|
||||
boolean isSensitive();
|
||||
|
||||
/**
|
||||
* Returns the {@link MediaType}s that this endpoint produces or {@code null}.
|
||||
*/
|
||||
MediaType[] produces();
|
||||
|
||||
/**
|
||||
* Returns the {@link HttpMethod}s that this endpoint supports.
|
||||
*/
|
||||
HttpMethod[] methods();
|
||||
|
||||
/**
|
||||
* Called to invoke the endpoint.
|
||||
* @return the results of the invocation
|
||||
|
||||
@@ -43,11 +43,11 @@ public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> i
|
||||
* Create a new {@link EnvironmentEndpoint} instance.
|
||||
*/
|
||||
public EnvironmentEndpoint() {
|
||||
super("/env");
|
||||
super("env");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doInvoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
result.put("profiles", this.environment.getActiveProfiles());
|
||||
for (PropertySource<?> source : getPropertySources()) {
|
||||
@@ -71,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 : "******";
|
||||
|
||||
@@ -36,13 +36,13 @@ public class HealthEndpoint<T> extends AbstractEndpoint<T> {
|
||||
* @param indicator the health indicator
|
||||
*/
|
||||
public HealthEndpoint(HealthIndicator<? extends T> indicator) {
|
||||
super("/health", false, true);
|
||||
super("health", false, true);
|
||||
Assert.notNull(indicator, "Indicator must not be null");
|
||||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T doInvoke() {
|
||||
public T invoke() {
|
||||
return this.indicator.health();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
* @param info the info to expose
|
||||
*/
|
||||
public InfoEndpoint(Map<String, ? extends Object> info) {
|
||||
super("/info", false, true);
|
||||
super("info", false, true);
|
||||
Assert.notNull(info, "Info must not be null");
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doInvoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(this.info);
|
||||
info.putAll(getAdditionalInfo());
|
||||
return info;
|
||||
|
||||
@@ -39,13 +39,13 @@ public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
* @param metrics the metrics to expose
|
||||
*/
|
||||
public MetricsEndpoint(PublicMetrics metrics) {
|
||||
super("/metrics");
|
||||
super("metrics");
|
||||
Assert.notNull(metrics, "Metrics must not be null");
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doInvoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
for (Metric metric : this.metrics.metrics()) {
|
||||
result.put(metric.getName(), metric.getValue());
|
||||
|
||||
@@ -24,7 +24,6 @@ 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.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to shutdown the {@link ApplicationContext}.
|
||||
@@ -42,32 +41,37 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> impl
|
||||
* Create a new {@link ShutdownEndpoint} instance.
|
||||
*/
|
||||
public ShutdownEndpoint() {
|
||||
super("/shutdown", true, false);
|
||||
super("shutdown", true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doInvoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
|
||||
if (this.context == null) {
|
||||
return Collections.<String, Object> singletonMap("message",
|
||||
"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
|
||||
@@ -77,9 +81,4 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod[] methods() {
|
||||
return POST_HTTP_METHOD;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,13 +39,13 @@ public class TraceEndpoint extends AbstractEndpoint<List<Trace>> {
|
||||
* @param repository the trace repository
|
||||
*/
|
||||
public TraceEndpoint(TraceRepository repository) {
|
||||
super("/trace");
|
||||
super("trace");
|
||||
Assert.notNull(repository, "Repository must not be null");
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Trace> doInvoke() {
|
||||
public List<Trace> invoke() {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointDisabledException;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;
|
||||
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
/**
|
||||
* MVC {@link HandlerAdapter} for {@link Endpoint}s. Similar in may respects to
|
||||
* {@link AbstractMessageConverterMethodProcessor} but not tied to annotated methods.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*
|
||||
* @see EndpointHandlerMapping
|
||||
*/
|
||||
public final class EndpointHandlerAdapter implements HandlerAdapter {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private static final MediaType MEDIA_TYPE_APPLICATION = new MediaType("application");
|
||||
|
||||
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
|
||||
|
||||
private List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private List<MediaType> allSupportedMediaTypes;
|
||||
|
||||
public EndpointHandlerAdapter() {
|
||||
WebMvcConfigurationSupportConventions conventions = new WebMvcConfigurationSupportConventions();
|
||||
setMessageConverters(conventions.getDefaultHttpMessageConverters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Object handler) {
|
||||
return handler instanceof Endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(HttpServletRequest request, Object handler) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
handle(request, response, (Endpoint<?>) handler);
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Endpoint<?> endpoint) throws Exception {
|
||||
|
||||
Object result = null;
|
||||
try {
|
||||
result = endpoint.invoke();
|
||||
}
|
||||
catch (EndpointDisabledException e) {
|
||||
// Disabled endpoints should get mapped to a HTTP 404
|
||||
throw new NoSuchRequestHandlingMethodException(request);
|
||||
}
|
||||
|
||||
Class<?> resultClass = result.getClass();
|
||||
|
||||
List<MediaType> mediaTypes = getMediaTypes(request, endpoint, resultClass);
|
||||
MediaType selectedMediaType = selectMediaType(mediaTypes);
|
||||
|
||||
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
|
||||
try {
|
||||
if (selectedMediaType != null) {
|
||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
if (messageConverter.canWrite(resultClass, selectedMediaType)) {
|
||||
((HttpMessageConverter<Object>) messageConverter).write(result,
|
||||
selectedMediaType, outputMessage);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Written [" + result + "] as \""
|
||||
+ selectedMediaType + "\" using [" + messageConverter
|
||||
+ "]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
|
||||
}
|
||||
finally {
|
||||
outputMessage.close();
|
||||
}
|
||||
}
|
||||
|
||||
private List<MediaType> getMediaTypes(HttpServletRequest request,
|
||||
Endpoint<?> endpoint, Class<?> resultClass)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> requested = getAcceptableMediaTypes(request);
|
||||
List<MediaType> producible = getProducibleMediaTypes(endpoint, resultClass);
|
||||
|
||||
Set<MediaType> compatible = new LinkedHashSet<MediaType>();
|
||||
for (MediaType r : requested) {
|
||||
for (MediaType p : producible) {
|
||||
if (r.isCompatibleWith(p)) {
|
||||
compatible.add(getMostSpecificMediaType(r, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compatible.isEmpty()) {
|
||||
throw new HttpMediaTypeNotAcceptableException(producible);
|
||||
}
|
||||
List<MediaType> mediaTypes = new ArrayList<MediaType>(compatible);
|
||||
MediaType.sortBySpecificityAndQuality(mediaTypes);
|
||||
return mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
List<MediaType> mediaTypes = this.contentNegotiationManager
|
||||
.resolveMediaTypes(new ServletWebRequest(request));
|
||||
return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL)
|
||||
: mediaTypes;
|
||||
}
|
||||
|
||||
private List<MediaType> getProducibleMediaTypes(Endpoint<?> endpoint,
|
||||
Class<?> returnValueClass) {
|
||||
MediaType[] mediaTypes = endpoint.produces();
|
||||
if (mediaTypes != null && mediaTypes.length != 0) {
|
||||
return Arrays.asList(mediaTypes);
|
||||
}
|
||||
|
||||
if (this.allSupportedMediaTypes.isEmpty()) {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
|
||||
List<MediaType> result = new ArrayList<MediaType>();
|
||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(returnValueClass, null)) {
|
||||
result.addAll(converter.getSupportedMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
produceType = produceType.copyQualityValue(acceptType);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) <= 0 ? acceptType
|
||||
: produceType;
|
||||
}
|
||||
|
||||
private MediaType selectMediaType(List<MediaType> mediaTypes) {
|
||||
MediaType selectedMediaType = null;
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
if (mediaType.isConcrete()) {
|
||||
selectedMediaType = mediaType;
|
||||
break;
|
||||
}
|
||||
else if (mediaType.equals(MediaType.ALL)
|
||||
|| mediaType.equals(MEDIA_TYPE_APPLICATION)) {
|
||||
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return selectedMediaType;
|
||||
}
|
||||
|
||||
public void setContentNegotiationManager(
|
||||
ContentNegotiationManager contentNegotiationManager) {
|
||||
this.contentNegotiationManager = contentNegotiationManager;
|
||||
}
|
||||
|
||||
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
this.messageConverters = messageConverters;
|
||||
Set<MediaType> allSupportedMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
|
||||
}
|
||||
this.allSupportedMediaTypes = new ArrayList<MediaType>(allSupportedMediaTypes);
|
||||
MediaType.sortBySpecificity(this.allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default conventions, taken from {@link WebMvcConfigurationSupport} with a few minor
|
||||
* tweaks.
|
||||
*/
|
||||
private static class WebMvcConfigurationSupportConventions extends
|
||||
WebMvcConfigurationSupport {
|
||||
public List<HttpMessageConverter<?>> getDefaultHttpMessageConverters() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
addDefaultHttpMessageConverters(converters);
|
||||
for (HttpMessageConverter<?> converter : converters) {
|
||||
if (converter instanceof MappingJackson2HttpMessageConverter) {
|
||||
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
|
||||
jacksonConverter.getObjectMapper().disable(
|
||||
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
}
|
||||
}
|
||||
return converters;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,36 +16,42 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
* {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getPath()}.
|
||||
* {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getId()}.
|
||||
* The semantics of {@code @RequestMapping} should be identical to a normal
|
||||
* {@code @Controller}, but the endpoints should not be annotated as {@code @Controller}
|
||||
* (otherwise they will be mapped by the normal MVC mechanisms).
|
||||
*
|
||||
* <p>
|
||||
* One of the aims of the mapping is to support endpoints that work as HTTP endpoints but
|
||||
* can still provide useful service interfaces when there is no HTTP server (and no Spring
|
||||
* MVC on the classpath). Note that any endpoints having method signaturess will break in
|
||||
* a non-servlet environment.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Christian Dupuis
|
||||
* @see EndpointHandlerAdapter
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
InitializingBean, ApplicationContextAware {
|
||||
public class EndpointHandlerMapping extends RequestMappingHandlerMapping implements
|
||||
ApplicationContextAware {
|
||||
|
||||
private List<Endpoint<?>> endpoints;
|
||||
private Set<? extends MvcEndpoint> endpoints;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
@@ -54,52 +60,74 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be
|
||||
* detected from the {@link ApplicationContext}.
|
||||
* @param endpoints
|
||||
*/
|
||||
public EndpointHandlerMapping() {
|
||||
setOrder(HIGHEST_PRECEDENCE);
|
||||
public EndpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
|
||||
this.endpoints = new HashSet<MvcEndpoint>(endpoints);
|
||||
// By default the static resource handler mapping is LOWEST_PRECEDENCE - 1
|
||||
setOrder(LOWEST_PRECEDENCE - 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
if (!this.disabled) {
|
||||
for (MvcEndpoint endpoint : this.endpoints) {
|
||||
detectHandlerMethods(endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} with the specified endpoints.
|
||||
* @param endpoints the endpoints
|
||||
* Since all handler beans are passed into the constructor there is no need to detect
|
||||
* anything here
|
||||
*/
|
||||
public EndpointHandlerMapping(Collection<? extends Endpoint<?>> endpoints) {
|
||||
Assert.notNull(endpoints, "Endpoints must not be null");
|
||||
this.endpoints = new ArrayList<Endpoint<?>>(endpoints);
|
||||
@Override
|
||||
protected boolean isHandler(Class<?> beanType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.endpoints == null) {
|
||||
this.endpoints = findEndpointBeans();
|
||||
protected void registerHandlerMethod(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
|
||||
if (mapping == null) {
|
||||
return;
|
||||
}
|
||||
if (!this.disabled) {
|
||||
for (Endpoint<?> endpoint : this.endpoints) {
|
||||
registerHandler(this.prefix + endpoint.getPath(), endpoint);
|
||||
|
||||
Set<String> defaultPatterns = mapping.getPatternsCondition().getPatterns();
|
||||
String[] patterns = new String[defaultPatterns.isEmpty() ? 1 : defaultPatterns
|
||||
.size()];
|
||||
|
||||
String path = "";
|
||||
Object bean = handler;
|
||||
if (bean instanceof String) {
|
||||
bean = getApplicationContext().getBean((String) handler);
|
||||
}
|
||||
if (bean instanceof MvcEndpoint) {
|
||||
MvcEndpoint endpoint = (MvcEndpoint) bean;
|
||||
path = endpoint.getPath();
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
String prefix = StringUtils.hasText(this.prefix) ? this.prefix + path : path;
|
||||
if (defaultPatterns.isEmpty()) {
|
||||
patterns[0] = prefix;
|
||||
}
|
||||
else {
|
||||
for (String pattern : defaultPatterns) {
|
||||
patterns[i] = prefix + pattern;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns);
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private List<Endpoint<?>> findEndpointBeans() {
|
||||
return new ArrayList(BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
getApplicationContext(), Endpoint.class).values());
|
||||
}
|
||||
RequestMappingInfo modified = new RequestMappingInfo(patternsInfo,
|
||||
mapping.getMethodsCondition(), mapping.getParamsCondition(),
|
||||
mapping.getHeadersCondition(), mapping.getConsumesCondition(),
|
||||
mapping.getProducesCondition(), mapping.getCustomCondition());
|
||||
|
||||
@Override
|
||||
protected Object lookupHandler(String urlPath, HttpServletRequest request)
|
||||
throws Exception {
|
||||
Object handler = super.lookupHandler(urlPath, request);
|
||||
if (handler != null) {
|
||||
Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler)
|
||||
.getHandler() : handler);
|
||||
HttpMethod method = HttpMethod.valueOf(request.getMethod());
|
||||
if (endpoint instanceof Endpoint
|
||||
&& supportsMethod(((Endpoint<?>) endpoint).methods(), method)) {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
super.registerHandlerMethod(handler, method, modified);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,19 +156,7 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
/**
|
||||
* Return the endpoints
|
||||
*/
|
||||
public List<Endpoint<?>> getEndpoints() {
|
||||
return Collections.unmodifiableList(this.endpoints);
|
||||
}
|
||||
|
||||
private boolean supportsMethod(HttpMethod[] supportedMethods,
|
||||
HttpMethod requestedMethod) {
|
||||
Assert.notNull(supportedMethods, "SupportMethods must not be null");
|
||||
Assert.notNull(supportedMethods, "RequestedMethod must not be null");
|
||||
for (HttpMethod supportedMethod : supportedMethods) {
|
||||
if (supportedMethod.equals(requestedMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public Set<? extends MvcEndpoint> getEndpoints() {
|
||||
return this.endpoints;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class EnvironmentMvcEndpoint extends GenericMvcEndpoint implements
|
||||
EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
public EnvironmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
|
||||
@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,59 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
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.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.delegate.isSensitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Endpoint<?>> type = (Class<? extends Endpoint<?>>) this.delegate
|
||||
.getClass();
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,10 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} implementation to register the Jolokia infrastructure with the Boot
|
||||
@@ -26,20 +29,49 @@ import org.springframework.http.HttpMethod;
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.jolokia", ignoreUnknownFields = false)
|
||||
public class JolokiaEndpoint extends AbstractEndpoint<String> {
|
||||
public class JolokiaMvcEndpoint implements MvcEndpoint {
|
||||
|
||||
public JolokiaEndpoint() {
|
||||
super("/jolokia");
|
||||
@NotNull
|
||||
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
||||
private String path;
|
||||
|
||||
private boolean sensitive;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
public JolokiaMvcEndpoint() {
|
||||
this.path = "/jolokia";
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInvoke() {
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod[] methods() {
|
||||
return NO_HTTP_METHOD;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
/**
|
||||
* Special endpoint for handling "/error" path when the management servlet is in a child
|
||||
* context. The regular {@link ErrorController} should be available there but because of
|
||||
* the way the handler mappings are set up it will not be detected.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "error")
|
||||
public class ManagementErrorEndpoint implements MvcEndpoint {
|
||||
|
||||
private final ErrorController controller;
|
||||
private String path;
|
||||
|
||||
public ManagementErrorEndpoint(String path, ErrorController controller) {
|
||||
this.path = path;
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Map<String, Object> invoke() {
|
||||
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
|
||||
return this.controller.extract(attributes, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class MetricsMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
private MetricsEndpoint delegate;
|
||||
|
||||
public MetricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||
super(delegate);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
|
||||
@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,38 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A strategy for the MVC layer on top of an {@link Endpoint}. Implementations are allowed
|
||||
* to use <code>@RequestMapping</code> and the full Spring MVC machinery, but should not
|
||||
* use <code>@Controller</code> or <code>@RequestMapping</code> at the type level (since
|
||||
* that would lead to a double mapping of paths, once by the regular MVC handler mappings
|
||||
* and once by the {@link EndpointHandlerMapping}).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface MvcEndpoint {
|
||||
|
||||
String getPath();
|
||||
|
||||
boolean isSensitive();
|
||||
|
||||
Class<?> getEndpointType();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A registry for all {@link MvcEndpoint} beans, and a factory for a set of generic ones
|
||||
* wrapping existing {@link Endpoint} instances that are not already exposed as MVC
|
||||
* endpoints.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Component
|
||||
public class MvcEndpoints implements ApplicationContextAware, InitializingBean {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Set<MvcEndpoint> endpoints = new HashSet<MvcEndpoint>();
|
||||
|
||||
private Set<Class<?>> customTypes;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Collection<MvcEndpoint> existing = this.applicationContext.getBeansOfType(
|
||||
MvcEndpoint.class).values();
|
||||
this.endpoints.addAll(existing);
|
||||
this.customTypes = findEndpointClasses(existing);
|
||||
@SuppressWarnings("rawtypes")
|
||||
Collection<Endpoint> delegates = this.applicationContext.getBeansOfType(
|
||||
Endpoint.class).values();
|
||||
for (Endpoint<?> endpoint : delegates) {
|
||||
if (isGenericEndpoint(endpoint.getClass())) {
|
||||
this.endpoints.add(new GenericMvcEndpoint(endpoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Class<?>> findEndpointClasses(Collection<MvcEndpoint> existing) {
|
||||
Set<Class<?>> types = new HashSet<Class<?>>();
|
||||
for (MvcEndpoint endpoint : existing) {
|
||||
Class<?> type = endpoint.getEndpointType();
|
||||
if (type != null) {
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
public Set<? extends MvcEndpoint> getEndpoints() {
|
||||
return this.endpoints;
|
||||
}
|
||||
|
||||
private boolean isGenericEndpoint(Class<?> type) {
|
||||
return !this.customTypes.contains(type)
|
||||
&& !MvcEndpoint.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
public class ShutdownMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public ShutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
@Override
|
||||
public Object invoke() {
|
||||
return super.invoke();
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class BasicErrorController implements ErrorController {
|
||||
|
||||
@RequestMapping(value = "${error.path:/error}", produces = "text/html")
|
||||
public ModelAndView errorHtml(HttpServletRequest request) {
|
||||
Map<String, Object> map = extract(new ServletRequestAttributes(request), false);
|
||||
Map<String, Object> map = error(request);
|
||||
return new ModelAndView(ERROR_KEY, map);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import java.nio.charset.Charset;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.TestUtils;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
@@ -200,13 +200,8 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Endpoint<String> testEndpoint() {
|
||||
return new AbstractEndpoint<String>("/endpoint", false, true) {
|
||||
@Override
|
||||
public String doInvoke() {
|
||||
return "endpointoutput";
|
||||
}
|
||||
};
|
||||
public TestEndpoint testEndpoint() {
|
||||
return new TestEndpoint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,4 +240,29 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
public static class TestEndpoint implements MvcEndpoint {
|
||||
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public String invoke() {
|
||||
return "endpointoutput";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return "/endpoint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
return Endpoint.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ public class JolokiaAutoConfigurationTests {
|
||||
public void agentServletRegisteredWithAppContext() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
this.context.register(Config.class, WebMvcAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, JolokiaAutoConfiguration.class);
|
||||
ManagementServerPropertiesAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
JolokiaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertEquals(1, this.context.getBeanNamesForType(AgentServlet.class).length);
|
||||
}
|
||||
@@ -70,7 +72,9 @@ public class JolokiaAutoConfigurationTests {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
TestUtils.addEnviroment(this.context, "endpoints.jolokia.enabled:false");
|
||||
this.context.register(Config.class, WebMvcAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, JolokiaAutoConfiguration.class);
|
||||
ManagementServerPropertiesAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
JolokiaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertEquals(0, this.context.getBeanNamesForType(AgentServlet.class).length);
|
||||
}
|
||||
@@ -79,7 +83,9 @@ public class JolokiaAutoConfigurationTests {
|
||||
public void agentServletRegisteredWithServletContainer() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
this.context.register(Config.class, WebMvcAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, JolokiaAutoConfiguration.class);
|
||||
ManagementServerPropertiesAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
JolokiaAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
Servlet servlet = null;
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.boot.TestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@@ -43,22 +42,19 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
private final String path;
|
||||
private final String id;
|
||||
|
||||
private final boolean sensitive;
|
||||
|
||||
private final String property;
|
||||
|
||||
private MediaType[] produces;
|
||||
|
||||
public AbstractEndpointTests(Class<?> configClass, Class<?> type, String path,
|
||||
boolean sensitive, String property, MediaType... produces) {
|
||||
public AbstractEndpointTests(Class<?> configClass, Class<?> type, String id,
|
||||
boolean sensitive, String property) {
|
||||
this.configClass = configClass;
|
||||
this.type = type;
|
||||
this.path = path;
|
||||
this.id = id;
|
||||
this.sensitive = sensitive;
|
||||
this.property = property;
|
||||
this.produces = produces;
|
||||
}
|
||||
|
||||
@Before
|
||||
@@ -76,13 +72,8 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void producesMediaType() {
|
||||
assertThat(getEndpointBean().produces(), equalTo(this.produces));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPath() throws Exception {
|
||||
assertThat(getEndpointBean().getPath(), equalTo(this.path));
|
||||
public void getId() throws Exception {
|
||||
assertThat(getEndpointBean().getId(), equalTo(this.id));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,12 +82,12 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathOverride() throws Exception {
|
||||
public void idOverride() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
TestUtils.addEnviroment(this.context, this.property + ".path:/mypath");
|
||||
TestUtils.addEnviroment(this.context, this.property + ".id:myid");
|
||||
this.context.register(this.configClass);
|
||||
this.context.refresh();
|
||||
assertThat(getEndpointBean().getPath(), equalTo("/mypath"));
|
||||
assertThat(getEndpointBean().getId(), equalTo("myid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -42,7 +42,7 @@ public class AutoConfigurationReportEndpointTests extends
|
||||
AbstractEndpointTests<AutoConfigurationReportEndpoint> {
|
||||
|
||||
public AutoConfigurationReportEndpointTests() {
|
||||
super(Config.class, AutoConfigurationReportEndpoint.class, "/autoconfig", true,
|
||||
super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig", true,
|
||||
"endpoints.autoconfig");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.BeansEndpoint;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
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}.
|
||||
@@ -34,13 +35,14 @@ import static org.junit.Assert.assertThat;
|
||||
public class BeansEndpointTests extends AbstractEndpointTests<BeansEndpoint> {
|
||||
|
||||
public BeansEndpointTests() {
|
||||
super(Config.class, BeansEndpoint.class, "/beans", true, "endpoints.beans",
|
||||
MediaType.APPLICATION_JSON);
|
||||
super(Config.class, BeansEndpoint.class, "beans", true, "endpoints.beans");
|
||||
}
|
||||
|
||||
@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
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ConfigurationPropertiesReportEndpointParentTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
if (this.context.getParent() != null) {
|
||||
((ConfigurableApplicationContext) this.context.getParent()).close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvoke() throws Exception {
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
|
||||
parent.register(Parent.class);
|
||||
parent.refresh();
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.setParent(parent);
|
||||
this.context.register(Config.class);
|
||||
this.context.refresh();
|
||||
ConfigurationPropertiesReportEndpoint endpoint = this.context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
Map<String, Object> result = endpoint.invoke();
|
||||
assertTrue(result.containsKey("parent"));
|
||||
assertEquals(3, result.size()); // the endpoint, the test props and the parent
|
||||
// System.err.println(result);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Parent {
|
||||
@Bean
|
||||
public TestProperties testProperties() {
|
||||
return new TestProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public ConfigurationPropertiesReportEndpoint endpoint() {
|
||||
return new ConfigurationPropertiesReportEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestProperties testProperties() {
|
||||
return new TestProperties();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(name = "test")
|
||||
public static class TestProperties {
|
||||
|
||||
private String myTestProperty = "654321";
|
||||
|
||||
public String getMyTestProperty() {
|
||||
return this.myTestProperty;
|
||||
}
|
||||
|
||||
public void setMyTestProperty(String myTestProperty) {
|
||||
this.myTestProperty = myTestProperty;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
AbstractEndpointTests<ConfigurationPropertiesReportEndpoint> {
|
||||
|
||||
public ConfigurationPropertiesReportEndpointTests() {
|
||||
super(Config.class, ConfigurationPropertiesReportEndpoint.class, "/configprops",
|
||||
super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops",
|
||||
true, "endpoints.configprops");
|
||||
}
|
||||
|
||||
@@ -68,6 +68,15 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
assertEquals("******", nestedProperties.get("myTestProperty"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Parent {
|
||||
@Bean
|
||||
public TestProperties testProperties() {
|
||||
return new TestProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Config {
|
||||
@@ -82,29 +91,30 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
return new TestProperties();
|
||||
}
|
||||
|
||||
@ConfigurationProperties(name = "test")
|
||||
public static class TestProperties {
|
||||
}
|
||||
|
||||
private String dbPassword = "123456";
|
||||
@ConfigurationProperties(name = "test")
|
||||
public static class TestProperties {
|
||||
|
||||
private String myTestProperty = "654321";
|
||||
private String dbPassword = "123456";
|
||||
|
||||
public String getDbPassword() {
|
||||
return this.dbPassword;
|
||||
}
|
||||
|
||||
public void setDbPassword(String dbPassword) {
|
||||
this.dbPassword = dbPassword;
|
||||
}
|
||||
|
||||
public String getMyTestProperty() {
|
||||
return this.myTestProperty;
|
||||
}
|
||||
|
||||
public void setMyTestProperty(String myTestProperty) {
|
||||
this.myTestProperty = myTestProperty;
|
||||
}
|
||||
private String myTestProperty = "654321";
|
||||
|
||||
public String getDbPassword() {
|
||||
return this.dbPassword;
|
||||
}
|
||||
|
||||
public void setDbPassword(String dbPassword) {
|
||||
this.dbPassword = dbPassword;
|
||||
}
|
||||
|
||||
public String getMyTestProperty() {
|
||||
return this.myTestProperty;
|
||||
}
|
||||
|
||||
public void setMyTestProperty(String myTestProperty) {
|
||||
this.myTestProperty = myTestProperty;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.lang.management.ThreadInfo;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.DumpEndpoint;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -36,7 +35,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class DumpEndpointTests extends AbstractEndpointTests<DumpEndpoint> {
|
||||
|
||||
public DumpEndpointTests() {
|
||||
super(Config.class, DumpEndpoint.class, "/dump", true, "endpoints.dump");
|
||||
super(Config.class, DumpEndpoint.class, "dump", true, "endpoints.dump");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -33,7 +32,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentEndpoint> {
|
||||
|
||||
public EnvironmentEndpointTests() {
|
||||
super(Config.class, EnvironmentEndpoint.class, "/env", true, "endpoints.env");
|
||||
super(Config.class, EnvironmentEndpoint.class, "env", true, "endpoints.env");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -34,7 +33,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint<String>> {
|
||||
|
||||
public HealthEndpointTests() {
|
||||
super(Config.class, HealthEndpoint.class, "/health", false, "endpoints.health");
|
||||
super(Config.class, HealthEndpoint.class, "health", false, "endpoints.health");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -35,7 +35,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class InfoEndpointTests extends AbstractEndpointTests<InfoEndpoint> {
|
||||
|
||||
public InfoEndpointTests() {
|
||||
super(Config.class, InfoEndpoint.class, "/info", false, "endpoints.info");
|
||||
super(Config.class, InfoEndpoint.class, "info", false, "endpoints.info");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -20,8 +20,6 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.PublicMetrics;
|
||||
import org.springframework.boot.actuate.metrics.Metric;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -38,7 +36,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class MetricsEndpointTests extends AbstractEndpointTests<MetricsEndpoint> {
|
||||
|
||||
public MetricsEndpointTests() {
|
||||
super(Config.class, MetricsEndpoint.class, "/metrics", true, "endpoints.metrics");
|
||||
super(Config.class, MetricsEndpoint.class, "metrics", true, "endpoints.metrics");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -35,7 +35,7 @@ import static org.junit.Assert.assertTrue;
|
||||
public class ShutdownEndpointTests extends AbstractEndpointTests<ShutdownEndpoint> {
|
||||
|
||||
public ShutdownEndpointTests() {
|
||||
super(Config.class, ShutdownEndpoint.class, "/shutdown", true,
|
||||
super(Config.class, ShutdownEndpoint.class, "shutdown", true,
|
||||
"endpoints.shutdown");
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.boot.actuate.endpoint;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.TraceEndpoint;
|
||||
import org.springframework.boot.actuate.trace.InMemoryTraceRepository;
|
||||
import org.springframework.boot.actuate.trace.Trace;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
@@ -38,7 +37,7 @@ import static org.junit.Assert.assertThat;
|
||||
public class TraceEndpointTests extends AbstractEndpointTests<TraceEndpoint> {
|
||||
|
||||
public TraceEndpointTests() {
|
||||
super(Config.class, TraceEndpoint.class, "/trace", true, "endpoints.trace");
|
||||
super(Config.class, TraceEndpoint.class, "trace", true, "endpoints.trace");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -167,11 +167,11 @@ public class EndpointMBeanExporterTests {
|
||||
public static class TestEndpoint extends AbstractEndpoint<String> {
|
||||
|
||||
public TestEndpoint() {
|
||||
super("/test");
|
||||
super("test");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInvoke() {
|
||||
public String invoke() {
|
||||
return "hello world";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link EndpointHandlerAdapter}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class EndpointHandlerAdapterTests {
|
||||
|
||||
private EndpointHandlerAdapter adapter = new EndpointHandlerAdapter();
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
private MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
@Test
|
||||
public void onlySupportsEndpoints() throws Exception {
|
||||
assertTrue(this.adapter.supports(mock(Endpoint.class)));
|
||||
assertFalse(this.adapter.supports(mock(Object.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rendersJson() throws Exception {
|
||||
this.adapter.handle(this.request, this.response,
|
||||
new AbstractEndpoint<Map<String, String>>("/foo") {
|
||||
@Override
|
||||
protected Map<String, String> doInvoke() {
|
||||
return Collections.singletonMap("hello", "world");
|
||||
}
|
||||
});
|
||||
assertEquals("{\"hello\":\"world\"}", this.response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rendersString() throws Exception {
|
||||
this.request.addHeader("Accept", "text/plain");
|
||||
this.adapter.handle(this.request, this.response, new AbstractEndpoint<String>(
|
||||
"/foo") {
|
||||
@Override
|
||||
protected String doInvoke() {
|
||||
return "hello world";
|
||||
}
|
||||
});
|
||||
assertEquals("hello world", this.response.getContentAsString());
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,19 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
@@ -33,66 +40,94 @@ import static org.junit.Assert.assertThat;
|
||||
* Tests for {@link EndpointHandlerMapping}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class EndpointHandlerMappingTests {
|
||||
|
||||
private StaticApplicationContext context = new StaticApplicationContext();
|
||||
private Method method;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
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"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(Arrays.asList(
|
||||
endpointA, endpointB));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a"))
|
||||
.getHandler(), equalTo((Object) endpointA));
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointA, this.method)));
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/b"))
|
||||
.getHandler(), equalTo((Object) endpointB));
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointB, this.method)));
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/c")),
|
||||
nullValue());
|
||||
}
|
||||
|
||||
@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"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(Arrays.asList(
|
||||
endpointA, endpointB));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.setPrefix("/a");
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a/a"))
|
||||
.getHandler(), equalTo((Object) endpointA));
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointA, this.method)));
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a/b"))
|
||||
.getHandler(), equalTo((Object) endpointB));
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointB, this.method)));
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyGetHttpMethodForNonActionEndpoints() throws Exception {
|
||||
TestEndpoint endpoint = new TestEndpoint("/a");
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
assertNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onlyPostHttpMethodForActionEndpoints() throws Exception {
|
||||
TestEndpoint endpoint = new TestActionEndpoint("/a");
|
||||
public void postHttpMethodForActionEndpoints() throws Exception {
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNull(mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
}
|
||||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyPostHttpMethodForActionEndpoints() throws Exception {
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
assertNull(mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabled() throws Exception {
|
||||
TestEndpoint endpointA = new TestEndpoint("/a");
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpointA));
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setDisabled(true);
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
nullValue());
|
||||
@@ -105,22 +140,32 @@ public class EndpointHandlerMappingTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doInvoke() {
|
||||
public Object invoke() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestActionEndpoint extends TestEndpoint {
|
||||
private static class TestMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public TestActionEndpoint(String path) {
|
||||
super(path);
|
||||
public TestMvcEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestActionEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public TestActionEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod[] methods() {
|
||||
return POST_HTTP_METHOD;
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public Object invoke() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.TestUtils;
|
||||
import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpointTests.TestConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { TestConfiguration.class })
|
||||
@WebAppConfiguration
|
||||
public class EnvironmentMvcEndpointTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
TestUtils.addEnviroment((ConfigurableApplicationContext) this.context, "foo:bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void home() throws Exception {
|
||||
this.mvc.perform(get("/env")).andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("systemProperties")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sub() throws Exception {
|
||||
this.mvc.perform(get("/env/foo")).andExpect(status().isOk())
|
||||
.andExpect(content().string(equalToIgnoringCase("bar")));
|
||||
}
|
||||
|
||||
@Import(EndpointWebMvcAutoConfiguration.class)
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
public static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public EnvironmentEndpoint endpoint() {
|
||||
return new EnvironmentEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EnvironmentMvcEndpoint mvcEndpoint() {
|
||||
return new EnvironmentMvcEndpoint(endpoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 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.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.JolokiaEndpointTests.Config;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Christian Dupuis
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { Config.class })
|
||||
@WebAppConfiguration
|
||||
public class JolokiaEndpointTests {
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints endpoints;
|
||||
|
||||
@Test
|
||||
public void endpointRegistered() throws Exception {
|
||||
assertEquals(1, this.endpoints.getEndpoints().size());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@EnableWebMvc
|
||||
@Import(EndpointWebMvcAutoConfiguration.class)
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public JolokiaMvcEndpoint endpoint() {
|
||||
return new JolokiaMvcEndpoint();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,10 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration;
|
||||
import org.springframework.boot.actuate.web.BasicErrorControllerIntegrationTests.TestConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -81,7 +83,8 @@ public class BasicErrorControllerIntegrationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class,
|
||||
ManagementSecurityAutoConfiguration.class })
|
||||
public static class TestConfiguration {
|
||||
|
||||
// For manual testing
|
||||
|
||||
@@ -19,7 +19,9 @@ package org.springframework.boot.actuate.web;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -77,13 +79,15 @@ public class BasicErrorControllerSpecialIntegrationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class,
|
||||
ManagementSecurityAutoConfiguration.class })
|
||||
protected static class ParentConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class,
|
||||
ManagementSecurityAutoConfiguration.class })
|
||||
@EnableWebMvc
|
||||
protected static class WebMvcIncludedConfiguration {
|
||||
// For manual testing
|
||||
@@ -94,7 +98,19 @@ public class BasicErrorControllerSpecialIntegrationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class,
|
||||
ManagementSecurityAutoConfiguration.class })
|
||||
protected static class VanillaConfiguration {
|
||||
// For manual testing
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(VanillaConfiguration.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class,
|
||||
ManagementSecurityAutoConfiguration.class })
|
||||
protected static class ChildConfiguration {
|
||||
|
||||
// For manual testing
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<modules>
|
||||
<module>spring-boot-sample-actuator</module>
|
||||
<module>spring-boot-sample-actuator-log4j</module>
|
||||
<module>spring-boot-sample-actuator-noweb</module>
|
||||
<module>spring-boot-sample-actuator-ui</module>
|
||||
<module>spring-boot-sample-amqp</module>
|
||||
<module>spring-boot-sample-aop</module>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>0.5.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-actuator-noweb</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-boot-starter-shell-remote</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* 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.
|
||||
@@ -14,29 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
public class JolokiaEndpointTests extends AbstractEndpointTests<JolokiaEndpoint> {
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableConfigurationProperties
|
||||
@ComponentScan
|
||||
public class SampleActuatorNoWebApplication {
|
||||
|
||||
public JolokiaEndpointTests() {
|
||||
super(Config.class, JolokiaEndpoint.class, "/jolokia", true, "endpoints.jolokia");
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(SampleActuatorNoWebApplication.class, args);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public JolokiaEndpoint endpoint() {
|
||||
return new JolokiaEndpoint();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -0,0 +1,5 @@
|
||||
service.name: Phil
|
||||
shell.ssh.enabled: true
|
||||
shell.ssh.port: 2222
|
||||
shell.auth: simple
|
||||
shell.auth.simple.user.password: password
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.sample.actuator;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Basic integration tests for service demo application.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class SampleActuatorNoWebApplicationTests {
|
||||
|
||||
private static ConfigurableApplicationContext context;
|
||||
|
||||
@BeforeClass
|
||||
public static void start() throws Exception {
|
||||
Future<ConfigurableApplicationContext> future = Executors
|
||||
.newSingleThreadExecutor().submit(
|
||||
new Callable<ConfigurableApplicationContext>() {
|
||||
@Override
|
||||
public ConfigurableApplicationContext call() throws Exception {
|
||||
return SpringApplication
|
||||
.run(SampleActuatorNoWebApplication.class);
|
||||
}
|
||||
});
|
||||
context = future.get(60, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stop() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsExist() throws Exception {
|
||||
assertNotNull(context.getBean(MetricsEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops.ui;
|
||||
package org.springframework.boot.sample.actuator.ui;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops.ui;
|
||||
package org.springframework.boot.sample.actuator.ui;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.ui.SampleActuatorUiApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops.ui;
|
||||
package org.springframework.boot.sample.actuator.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -28,6 +28,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.ui.SampleActuatorUiApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* 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.
|
||||
@@ -14,13 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
/**
|
||||
* {@link RuntimeException} indicating an {@link Endpoint} implementation is not enabled.
|
||||
*
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
public class EndpointDisabledException extends RuntimeException {
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class HelloWorldService {
|
||||
|
||||
@Autowired
|
||||
private ServiceProperties configuration;
|
||||
|
||||
public String getHelloMessage() {
|
||||
return "Hello " + this.configuration.getName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.sample.actuator;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ConfigurationProperties(name = "service", ignoreUnknownFields = false)
|
||||
@Component
|
||||
public class ServiceProperties {
|
||||
|
||||
private String name = "World";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +27,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -30,6 +30,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -36,6 +36,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -30,6 +30,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -31,6 +31,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.sample.ops;
|
||||
package org.springframework.boot.sample.actuator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +27,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.sample.actuator.SampleActuatorApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -0,0 +1,29 @@
|
||||
package commands
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.AutoConfigurationReportEndpoint
|
||||
|
||||
class autoconfig {
|
||||
|
||||
@Usage("Display auto configuration report from ApplicationContext")
|
||||
@Command
|
||||
void main(InvocationContext context) {
|
||||
context.attributes['spring.beanfactory'].getBeansOfType(AutoConfigurationReportEndpoint.class).each { name, endpoint ->
|
||||
def report = endpoint.invoke()
|
||||
out.println "Endpoint: " + name + "\n\nPositive Matches:\n================\n"
|
||||
report.positiveMatches.each { key, list ->
|
||||
out.println key + ":"
|
||||
list.each { mandc ->
|
||||
out.println " " + mandc.condition + ": " + mandc.message
|
||||
}
|
||||
}
|
||||
out.println "\nNegative Matches\n================\n"
|
||||
report.negativeMatches.each { key, list ->
|
||||
out.println key + ":"
|
||||
list.each { mandc ->
|
||||
out.println " " + mandc.condition + ": " + mandc.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package commands
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.BeansEndpoint
|
||||
|
||||
class beans {
|
||||
|
||||
@Usage("Display beans in ApplicationContext")
|
||||
@Command
|
||||
def main(InvocationContext context) {
|
||||
def result = [:]
|
||||
context.attributes['spring.beanfactory'].getBeansOfType(BeansEndpoint.class).each { name, endpoint ->
|
||||
result.put(name, endpoint.invoke())
|
||||
}
|
||||
result.size() == 1 ? result.values()[0] : result
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user