73 changed files with 1370 additions and 677 deletions
@ -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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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(); |
||||||
|
} |
||||||
|
} |
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -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()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -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> |
||||||
@ -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)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
3
spring-boot-samples/spring-boot-sample-actuator-ui/src/test/java/org/springframework/boot/sample/ops/ui/SampleActuatorUiApplicationPortTests.java → spring-boot-samples/spring-boot-sample-actuator-ui/src/test/java/org/springframework/boot/sample/actuator/ui/SampleActuatorUiApplicationPortTests.java
3
spring-boot-samples/spring-boot-sample-actuator-ui/src/test/java/org/springframework/boot/sample/ops/ui/SampleActuatorUiApplicationPortTests.java → spring-boot-samples/spring-boot-sample-actuator-ui/src/test/java/org/springframework/boot/sample/actuator/ui/SampleActuatorUiApplicationPortTests.java
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/EndpointsPropertiesSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/EndpointsPropertiesSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/EndpointsPropertiesSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/EndpointsPropertiesSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/ManagementAddressSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/ManagementAddressSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/ManagementAddressSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/ManagementAddressSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/NoManagementSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/NoManagementSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/NoManagementSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/NoManagementSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/UnsecureManagementSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/UnsecureManagementSampleActuatorApplicationTests.java
3
spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/ops/UnsecureManagementSampleActuatorApplicationTests.java → spring-boot-samples/spring-boot-sample-actuator/src/test/java/org/springframework/boot/sample/actuator/UnsecureManagementSampleActuatorApplicationTests.java
@ -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 |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue