Commit 222ed44b authored by Stephane Nicoll's avatar Stephane Nicoll

Replace enabledByDefault to DefaultEnablement

This commit introduces a DefaultEnablement enum that replaces the
"enabledByDefault" boolean flag of Endpoint. This allows to better
control what indicates the default enablement of an endpoint.

With DefaultEnablement#ENABLED, the endpoint is enabled unless an
endpoint specific property says otherwise. With DefaultEnabled#DISABLED,
the endpoint is disabled unless an endpoint specific property says
otherwise. DefaultEnablement#NEUTRAL provides a dedicated option to
indicate that we should resort to the default settings in absence of
a specific property.

See gh-10161
parent 6cd624ba
...@@ -19,9 +19,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint; ...@@ -19,9 +19,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.OperationParameterMapper; import org.springframework.boot.actuate.endpoint.OperationParameterMapper;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory; import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory;
import org.springframework.boot.actuate.endpoint.convert.ConversionServiceOperationParameterMapper; import org.springframework.boot.actuate.endpoint.convert.ConversionServiceOperationParameterMapper;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
package org.springframework.boot.actuate.autoconfigure.endpoint; package org.springframework.boot.actuate.autoconfigure.endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure; import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -42,24 +43,24 @@ public class EndpointEnablementProvider { ...@@ -42,24 +43,24 @@ public class EndpointEnablementProvider {
* Return the {@link EndpointEnablement} of an endpoint with no specific tech * Return the {@link EndpointEnablement} of an endpoint with no specific tech
* exposure. * exposure.
* @param endpointId the id of the endpoint * @param endpointId the id of the endpoint
* @param enabledByDefault whether the endpoint is enabled by default or not * @param defaultEnablement the {@link DefaultEnablement} of the endpoint
* @return the {@link EndpointEnablement} of that endpoint * @return the {@link EndpointEnablement} of that endpoint
*/ */
public EndpointEnablement getEndpointEnablement(String endpointId, public EndpointEnablement getEndpointEnablement(String endpointId,
boolean enabledByDefault) { DefaultEnablement defaultEnablement) {
return getEndpointEnablement(endpointId, enabledByDefault, null); return getEndpointEnablement(endpointId, defaultEnablement, null);
} }
/** /**
* Return the {@link EndpointEnablement} of an endpoint for a specific tech exposure. * Return the {@link EndpointEnablement} of an endpoint for a specific tech exposure.
* @param endpointId the id of the endpoint * @param endpointId the id of the endpoint
* @param enabledByDefault whether the endpoint is enabled by default or not * @param defaultEnablement the {@link DefaultEnablement} of the endpoint
* @param exposure the requested {@link EndpointExposure} * @param exposure the requested {@link EndpointExposure}
* @return the {@link EndpointEnablement} of that endpoint for the specified * @return the {@link EndpointEnablement} of that endpoint for the specified
* {@link EndpointExposure} * {@link EndpointExposure}
*/ */
public EndpointEnablement getEndpointEnablement(String endpointId, public EndpointEnablement getEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) { DefaultEnablement defaultEnablement, EndpointExposure exposure) {
Assert.hasText(endpointId, "Endpoint id must have a value"); Assert.hasText(endpointId, "Endpoint id must have a value");
Assert.isTrue(!endpointId.equals("default"), Assert.isTrue(!endpointId.equals("default"),
"Endpoint id 'default' is a reserved " "Endpoint id 'default' is a reserved "
...@@ -74,10 +75,11 @@ public class EndpointEnablementProvider { ...@@ -74,10 +75,11 @@ public class EndpointEnablementProvider {
} }
// All endpoints specific attributes have been looked at. Checking default value // All endpoints specific attributes have been looked at. Checking default value
// for the endpoint // for the endpoint
if (!enabledByDefault) { if (defaultEnablement != DefaultEnablement.NEUTRAL) {
return getDefaultEndpointEnablement(endpointId, false, exposure); return getDefaultEndpointEnablement(endpointId,
(defaultEnablement == DefaultEnablement.ENABLED), exposure);
} }
return getGlobalEndpointEnablement(endpointId, enabledByDefault, exposure); return getGlobalEndpointEnablement(endpointId, defaultEnablement, exposure);
} }
private EndpointEnablement findEnablement(String endpointId, private EndpointEnablement findEnablement(String endpointId,
...@@ -89,7 +91,7 @@ public class EndpointEnablementProvider { ...@@ -89,7 +91,7 @@ public class EndpointEnablementProvider {
} }
private EndpointEnablement getGlobalEndpointEnablement(String endpointId, private EndpointEnablement getGlobalEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) { DefaultEnablement defaultEnablement, EndpointExposure exposure) {
EndpointEnablement result = findGlobalEndpointEnablement(exposure); EndpointEnablement result = findGlobalEndpointEnablement(exposure);
if (result != null) { if (result != null) {
return result; return result;
...@@ -98,7 +100,42 @@ public class EndpointEnablementProvider { ...@@ -98,7 +100,42 @@ public class EndpointEnablementProvider {
if (result != null) { if (result != null) {
return result; return result;
} }
return getDefaultEndpointEnablement(endpointId, enabledByDefault, exposure); boolean enablement = determineGlobalDefaultEnablement(defaultEnablement, exposure);
String message = determineGlobalDefaultMessage(endpointId, enablement, exposure,
defaultEnablement);
return new EndpointEnablement(enablement, message);
}
private boolean determineGlobalDefaultEnablement(DefaultEnablement defaultEnablement,
EndpointExposure exposure) {
if (defaultEnablement == DefaultEnablement.NEUTRAL) {
return exposure == null || exposure.isEnabledByDefault();
}
return (defaultEnablement == DefaultEnablement.ENABLED);
}
private String determineGlobalDefaultMessage(String endpointId, boolean enablement,
EndpointExposure exposure, DefaultEnablement defaultEnablement) {
StringBuilder message = new StringBuilder();
message.append(String.format("endpoint '%s' ", endpointId));
if (exposure != null) {
message.append(String.format("(%s) ", exposure.name().toLowerCase()));
}
message.append(String.format("is %s ", (enablement ? "enabled" : "disabled")));
if (defaultEnablement == DefaultEnablement.NEUTRAL) {
if (exposure != null) {
message.append(String.format("(default for %s endpoints)",
exposure.name().toLowerCase()));
}
else {
message.append("(default)");
}
}
else {
message.append("by default");
}
return message.toString();
} }
private EndpointEnablement findGlobalEndpointEnablement(EndpointExposure exposure) { private EndpointEnablement findGlobalEndpointEnablement(EndpointExposure exposure) {
......
...@@ -20,9 +20,9 @@ import java.util.Collection; ...@@ -20,9 +20,9 @@ import java.util.Collection;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.boot.actuate.endpoint.EndpointDiscoverer; import org.springframework.boot.actuate.endpoint.EndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.Operation; import org.springframework.boot.actuate.endpoint.Operation;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
/** /**
...@@ -61,7 +61,7 @@ public class EndpointProvider<T extends Operation> { ...@@ -61,7 +61,7 @@ public class EndpointProvider<T extends Operation> {
private boolean isEnabled(EndpointInfo<?> endpoint) { private boolean isEnabled(EndpointInfo<?> endpoint) {
return this.endpointEnablementProvider.getEndpointEnablement(endpoint.getId(), return this.endpointEnablementProvider.getEndpointEnablement(endpoint.getId(),
endpoint.isEnabledByDefault(), this.exposure).isEnabled(); endpoint.getDefaultEnablement(), this.exposure).isEnabled();
} }
} }
...@@ -22,22 +22,39 @@ import java.lang.annotation.Retention; ...@@ -22,22 +22,39 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
/** /**
* {@link Conditional} that checks whether an endpoint is enabled or not. Matches * {@link Conditional} that checks whether an endpoint is enabled or not. Matches
* according to the {@code enabledByDefault} flag {@code types} flag that the * according to the {@code defaultEnablement} and {@code types} flag that the
* {@link Endpoint} may be restricted to. * {@link Endpoint} may be restricted to.
* <p> * <p>
* If no specific {@code endpoints.<id>.*} or {@code endpoints.default.*} properties are * When an endpoint uses {@link DefaultEnablement#DISABLED}, it will only be enabled if
* defined, the condition matches the {@code enabledByDefault} value regardless of the * {@code endpoint.<name>.enabled}, {@code endpoint.<name>.jmx.enabled} or
* specific {@link EndpointExposure}, if any. If any property are set, they are evaluated * {@code endpoint.<name>.web.enabled} is {@code true}.
* with a sensible order of precedence.
* <p> * <p>
* When an endpoint uses {@link DefaultEnablement#ENABLED}, it will be enabled unless
* {@code endpoint.<name>.enabled}, {@code endpoint.<name>.jmx.enabled} or
* {@code endpoint.<name>.web.enabled} is {@code false}.
* <p>
* When an endpoint uses {@link DefaultEnablement#NEUTRAL}, it will be enabled if
* {@code endpoint.default.enabled}, {@code endpoint.default.jmx.enabled} or
* {@code endpoint.default.web.enabled} is {@code true} and
* {@code endpoint.<name>.enabled}, {@code endpoint.<name>.jmx.enabled} or
* {@code endpoint.<name>.web.enabled} has not been set to {@code false}.
* <p>
* If any properties are set, they are evaluated from most to least specific, e.g.
* considering a web endpoint with id {@code foo}:
* <ol>
* <li>endpoints.foo.web.enabled</li>
* <li>endpoints.foo.enabled</li>
* <li>endpoints.default.web.enabled</li>
* <li>endpoints.default.enabled</li>
* </ol>
* For instance if {@code endpoints.default.enabled} is {@code false} but * For instance if {@code endpoints.default.enabled} is {@code false} but
* {@code endpoints.<id>.enabled} is {@code true}, the condition will match. * {@code endpoints.<name>.enabled} is {@code true}, the condition will match.
* <p> * <p>
* This condition must be placed on a {@code @Bean} method producing an endpoint as its id * This condition must be placed on a {@code @Bean} method producing an endpoint as its id
* and other attributes are inferred from the {@link Endpoint} annotation set on the * and other attributes are inferred from the {@link Endpoint} annotation set on the
...@@ -53,7 +70,7 @@ import org.springframework.context.annotation.Conditional; ...@@ -53,7 +70,7 @@ import org.springframework.context.annotation.Conditional;
* ... * ...
* } * }
* *
* &#064;Endpoint(id = "my", enabledByDefault = false) * &#064;Endpoint(id = "my", defaultEnablement = DefaultEnablement.DISABLED)
* static class MyEndpoint { ... } * static class MyEndpoint { ... }
* *
* }</pre> * }</pre>
......
...@@ -18,8 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition; ...@@ -18,8 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointEnablement; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointEnablement;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointEnablementProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointEnablementProvider;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension;
import org.springframework.boot.autoconfigure.condition.ConditionMessage; import org.springframework.boot.autoconfigure.condition.ConditionMessage;
...@@ -106,7 +107,7 @@ class OnEnabledEndpointCondition extends SpringBootCondition { ...@@ -106,7 +107,7 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
} }
// If both types are set, all exposure technologies are exposed // If both types are set, all exposure technologies are exposed
EndpointExposure[] exposures = endpoint.exposure(); EndpointExposure[] exposures = endpoint.exposure();
return new EndpointAttributes(endpoint.id(), endpoint.enabledByDefault(), return new EndpointAttributes(endpoint.id(), endpoint.defaultEnablement(),
(exposures.length == 1 ? exposures[0] : null)); (exposures.length == 1 ? exposures[0] : null));
} }
...@@ -114,21 +115,23 @@ class OnEnabledEndpointCondition extends SpringBootCondition { ...@@ -114,21 +115,23 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
private final String id; private final String id;
private final boolean enabled; private final DefaultEnablement defaultEnablement;
private final EndpointExposure exposure; private final EndpointExposure exposure;
EndpointAttributes(String id, boolean enabled, EndpointExposure exposure) { EndpointAttributes(String id, DefaultEnablement defaultEnablement,
EndpointExposure exposure) {
if (!StringUtils.hasText(id)) { if (!StringUtils.hasText(id)) {
throw new IllegalStateException("Endpoint id could not be determined"); throw new IllegalStateException("Endpoint id could not be determined");
} }
this.id = id; this.id = id;
this.enabled = enabled; this.defaultEnablement = defaultEnablement;
this.exposure = exposure; this.exposure = exposure;
} }
public EndpointEnablement getEnablement(EndpointEnablementProvider provider) { public EndpointEnablement getEnablement(EndpointEnablementProvider provider) {
return provider.getEndpointEnablement(this.id, this.enabled, this.exposure); return provider.getEndpointEnablement(this.id, this.defaultEnablement,
this.exposure);
} }
} }
......
...@@ -23,9 +23,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -23,9 +23,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.endpoint.DefaultCachingConfigurationFactory; import org.springframework.boot.actuate.autoconfigure.endpoint.DefaultCachingConfigurationFactory;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.OperationParameterMapper; import org.springframework.boot.actuate.endpoint.OperationParameterMapper;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanRegistrar; import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanRegistrar;
import org.springframework.boot.actuate.endpoint.jmx.JmxEndpointOperation; import org.springframework.boot.actuate.endpoint.jmx.JmxEndpointOperation;
import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxAnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxAnnotationEndpointDiscoverer;
......
...@@ -18,8 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition; ...@@ -18,8 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
...@@ -297,7 +298,7 @@ public class ConditionalOnEnabledEndpointTests { ...@@ -297,7 +298,7 @@ public class ConditionalOnEnabledEndpointTests {
} }
@Endpoint(id = "bar", exposure = { EndpointExposure.WEB, @Endpoint(id = "bar", exposure = { EndpointExposure.WEB,
EndpointExposure.JMX }, enabledByDefault = false) EndpointExposure.JMX }, defaultEnablement = DefaultEnablement.DISABLED)
static class BarEndpoint { static class BarEndpoint {
} }
......
...@@ -27,6 +27,7 @@ import org.mockito.MockitoAnnotations; ...@@ -27,6 +27,7 @@ import org.mockito.MockitoAnnotations;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.web.WebEndpointOperation; import org.springframework.boot.actuate.endpoint.web.WebEndpointOperation;
...@@ -82,8 +83,10 @@ public class DefaultEndpointPathProviderTests { ...@@ -82,8 +83,10 @@ public class DefaultEndpointPathProviderTests {
private DefaultEndpointPathProvider createProvider(String contextPath) { private DefaultEndpointPathProvider createProvider(String contextPath) {
Collection<EndpointInfo<WebEndpointOperation>> endpoints = new ArrayList<>(); Collection<EndpointInfo<WebEndpointOperation>> endpoints = new ArrayList<>();
endpoints.add(new EndpointInfo<>("foo", true, Collections.emptyList())); endpoints.add(new EndpointInfo<>("foo", DefaultEnablement.ENABLED,
endpoints.add(new EndpointInfo<>("bar", true, Collections.emptyList())); Collections.emptyList()));
endpoints.add(new EndpointInfo<>("bar", DefaultEnablement.ENABLED,
Collections.emptyList()));
given(this.endpointProvider.getEndpoints()).willReturn(endpoints); given(this.endpointProvider.getEndpoints()).willReturn(endpoints);
ManagementServerProperties managementServerProperties = new ManagementServerProperties(); ManagementServerProperties managementServerProperties = new ManagementServerProperties();
managementServerProperties.setContextPath(contextPath); managementServerProperties.setContextPath(contextPath);
......
...@@ -21,6 +21,7 @@ import java.util.Map; ...@@ -21,6 +21,7 @@ import java.util.Map;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.web.OperationRequestPredicate; import org.springframework.boot.actuate.endpoint.web.OperationRequestPredicate;
...@@ -140,8 +141,8 @@ public class RequestMappingEndpointTests { ...@@ -140,8 +141,8 @@ public class RequestMappingEndpointTests {
(arguments) -> "Invoked", true, requestPredicate, "test"); (arguments) -> "Invoked", true, requestPredicate, "test");
WebMvcEndpointHandlerMapping mapping = new WebMvcEndpointHandlerMapping( WebMvcEndpointHandlerMapping mapping = new WebMvcEndpointHandlerMapping(
new EndpointMapping("application"), new EndpointMapping("application"),
Collections.singleton(new EndpointInfo<>("test", true, Collections.singleton(new EndpointInfo<>("test",
Collections.singleton(operation)))); DefaultEnablement.ENABLED, Collections.singleton(operation))));
mapping.setApplicationContext(new StaticApplicationContext()); mapping.setApplicationContext(new StaticApplicationContext());
mapping.afterPropertiesSet(); mapping.afterPropertiesSet();
return mapping; return mapping;
......
...@@ -20,6 +20,7 @@ import java.util.Collections; ...@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
...@@ -34,7 +35,7 @@ import org.springframework.context.ConfigurableApplicationContext; ...@@ -34,7 +35,7 @@ import org.springframework.context.ConfigurableApplicationContext;
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0 * @since 2.0.0
*/ */
@Endpoint(id = "shutdown", enabledByDefault = false) @Endpoint(id = "shutdown", defaultEnablement = DefaultEnablement.DISABLED)
public class ShutdownEndpoint implements ApplicationContextAware { public class ShutdownEndpoint implements ApplicationContextAware {
private static final Map<String, Object> NO_CONTEXT_MESSAGE = Collections private static final Map<String, Object> NO_CONTEXT_MESSAGE = Collections
......
/*
* Copyright 2012-2017 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;
/**
* Enumerate the enablement options for an endpoint.
*
* @author Stephane Nicoll
* @since 2.0.0
*/
public enum DefaultEnablement {
/**
* The endpoint is enabled unless explicitly disabled.
*/
ENABLED,
/**
* The endpoint is disabled unless explicitly enabled.
*/
DISABLED,
/**
* The endpoint's enablement defaults to the "default" settings.
*/
NEUTRAL
}
...@@ -14,10 +14,10 @@ ...@@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.endpoint.annotation; package org.springframework.boot.actuate.endpoint;
/** /**
* An enumeration of the available {@link Endpoint} exposure technologies. * An enumeration of the available exposure technologies for an endpoint.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 2.0.0 * @since 2.0.0
......
...@@ -29,7 +29,7 @@ public class EndpointInfo<T extends Operation> { ...@@ -29,7 +29,7 @@ public class EndpointInfo<T extends Operation> {
private final String id; private final String id;
private final boolean enabledByDefault; private final DefaultEnablement defaultEnablement;
private final Collection<T> operations; private final Collection<T> operations;
...@@ -37,12 +37,13 @@ public class EndpointInfo<T extends Operation> { ...@@ -37,12 +37,13 @@ public class EndpointInfo<T extends Operation> {
* Creates a new {@code EndpointInfo} describing an endpoint with the given {@code id} * Creates a new {@code EndpointInfo} describing an endpoint with the given {@code id}
* and {@code operations}. * and {@code operations}.
* @param id the id of the endpoint * @param id the id of the endpoint
* @param enabledByDefault whether or not the endpoint is enabled by default * @param defaultEnablement the {@link DefaultEnablement} of the endpoint
* @param operations the operations of the endpoint * @param operations the operations of the endpoint
*/ */
public EndpointInfo(String id, boolean enabledByDefault, Collection<T> operations) { public EndpointInfo(String id, DefaultEnablement defaultEnablement,
Collection<T> operations) {
this.id = id; this.id = id;
this.enabledByDefault = enabledByDefault; this.defaultEnablement = defaultEnablement;
this.operations = operations; this.operations = operations;
} }
...@@ -55,11 +56,11 @@ public class EndpointInfo<T extends Operation> { ...@@ -55,11 +56,11 @@ public class EndpointInfo<T extends Operation> {
} }
/** /**
* Returns whether or not this endpoint is enabled by default. * Return the {@link DefaultEnablement} of the endpoint.
* @return {@code true} if it is enabled by default, otherwise {@code false} * @return the default enablement
*/ */
public boolean isEnabledByDefault() { public DefaultEnablement getDefaultEnablement() {
return this.enabledByDefault; return this.defaultEnablement;
} }
/** /**
......
...@@ -29,7 +29,9 @@ import java.util.function.Consumer; ...@@ -29,7 +29,9 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointDiscoverer; import org.springframework.boot.actuate.endpoint.EndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.Operation; import org.springframework.boot.actuate.endpoint.Operation;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
...@@ -117,9 +119,10 @@ public abstract class AnnotationEndpointDiscoverer<T extends Operation, K> ...@@ -117,9 +119,10 @@ public abstract class AnnotationEndpointDiscoverer<T extends Operation, K>
private EndpointInfo<T> createEndpointInfo(String beanName, Class<?> beanType, private EndpointInfo<T> createEndpointInfo(String beanName, Class<?> beanType,
AnnotationAttributes attributes) { AnnotationAttributes attributes) {
String id = attributes.getString("id"); String id = attributes.getString("id");
boolean enabledByDefault = attributes.getBoolean("enabledByDefault"); DefaultEnablement defaultEnablement = (DefaultEnablement) attributes.get(
"defaultEnablement");
Map<Method, T> operations = discoverOperations(id, beanName, beanType); Map<Method, T> operations = discoverOperations(id, beanName, beanType);
return new EndpointInfo<>(id, enabledByDefault, operations.values()); return new EndpointInfo<>(id, defaultEnablement, operations.values());
} }
private Map<Class<?>, EndpointExtensionInfo<T>> discoverExtensions( private Map<Class<?>, EndpointExtensionInfo<T>> discoverExtensions(
...@@ -192,7 +195,7 @@ public abstract class AnnotationEndpointDiscoverer<T extends Operation, K> ...@@ -192,7 +195,7 @@ public abstract class AnnotationEndpointDiscoverer<T extends Operation, K>
.put(this.operationKeyFactory.apply(operation), operation); .put(this.operationKeyFactory.apply(operation), operation);
endpoint.getOperations().forEach(consumer); endpoint.getOperations().forEach(consumer);
extension.getOperations().forEach(consumer); extension.getOperations().forEach(consumer);
return new EndpointInfo<>(endpoint.getId(), endpoint.isEnabledByDefault(), return new EndpointInfo<>(endpoint.getId(), endpoint.getDefaultEnablement(),
operations.values()); operations.values());
} }
......
...@@ -22,14 +22,15 @@ import java.lang.annotation.Retention; ...@@ -22,14 +22,15 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.boot.actuate.endpoint.EndpointDiscoverer; import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
/** /**
* Identifies a type as being an endpoint. * Identifies a type as being an endpoint.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0 * @since 2.0.0
* @see EndpointDiscoverer * @see AnnotationEndpointDiscoverer
*/ */
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
...@@ -50,9 +51,10 @@ public @interface Endpoint { ...@@ -50,9 +51,10 @@ public @interface Endpoint {
EndpointExposure[] exposure() default {}; EndpointExposure[] exposure() default {};
/** /**
* Whether or not the endpoint is enabled by default. * Defines the {@link DefaultEnablement} of the endpoint. By default, the endpoint's
* @return {@code true} if the endpoint is enabled by default, otherwise {@code false} * enablement defaults to the "default" settings.
* @return the default enablement
*/ */
boolean enabledByDefault() default true; DefaultEnablement defaultEnablement() default DefaultEnablement.NEUTRAL;
} }
...@@ -26,6 +26,7 @@ import java.util.List; ...@@ -26,6 +26,7 @@ import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.OperationParameterMapper; import org.springframework.boot.actuate.endpoint.OperationParameterMapper;
...@@ -33,7 +34,6 @@ import org.springframework.boot.actuate.endpoint.OperationType; ...@@ -33,7 +34,6 @@ import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration; import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration;
import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory; import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory;
import org.springframework.boot.actuate.endpoint.cache.CachingOperationInvoker; import org.springframework.boot.actuate.endpoint.cache.CachingOperationInvoker;
......
...@@ -27,6 +27,7 @@ import java.util.stream.Stream; ...@@ -27,6 +27,7 @@ import java.util.stream.Stream;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.OperationParameterMapper; import org.springframework.boot.actuate.endpoint.OperationParameterMapper;
...@@ -34,7 +35,6 @@ import org.springframework.boot.actuate.endpoint.OperationType; ...@@ -34,7 +35,6 @@ import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer; import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.Selector; import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration; import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration;
import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory; import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory;
......
...@@ -21,8 +21,8 @@ import java.io.File; ...@@ -21,8 +21,8 @@ import java.io.File;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
......
...@@ -36,8 +36,8 @@ import java.util.concurrent.locks.ReentrantLock; ...@@ -36,8 +36,8 @@ import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
......
...@@ -25,6 +25,7 @@ import javax.management.MBeanParameterInfo; ...@@ -25,6 +25,7 @@ import javax.management.MBeanParameterInfo;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
...@@ -47,8 +48,8 @@ public class EndpointMBeanInfoAssemblerTests { ...@@ -47,8 +48,8 @@ public class EndpointMBeanInfoAssemblerTests {
JmxEndpointOperation operation = new JmxEndpointOperation(OperationType.READ, JmxEndpointOperation operation = new JmxEndpointOperation(OperationType.READ,
new DummyOperationInvoker(), "getAll", Object.class, "Test operation", new DummyOperationInvoker(), "getAll", Object.class, "Test operation",
Collections.emptyList()); Collections.emptyList());
EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("test", true, EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("test",
Collections.singletonList(operation)); DefaultEnablement.ENABLED, Collections.singletonList(operation));
EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler
.createEndpointMBeanInfo(endpoint); .createEndpointMBeanInfo(endpoint);
assertThat(endpointMBeanInfo).isNotNull(); assertThat(endpointMBeanInfo).isNotNull();
...@@ -77,8 +78,8 @@ public class EndpointMBeanInfoAssemblerTests { ...@@ -77,8 +78,8 @@ public class EndpointMBeanInfoAssemblerTests {
new DummyOperationInvoker(), "update", Object.class, "Update operation", new DummyOperationInvoker(), "update", Object.class, "Update operation",
Collections.singletonList(new JmxEndpointOperationParameterInfo("test", Collections.singletonList(new JmxEndpointOperationParameterInfo("test",
String.class, "Test argument"))); String.class, "Test argument")));
EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("another", true, EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("another",
Collections.singletonList(operation)); DefaultEnablement.ENABLED, Collections.singletonList(operation));
EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler
.createEndpointMBeanInfo(endpoint); .createEndpointMBeanInfo(endpoint);
assertThat(endpointMBeanInfo).isNotNull(); assertThat(endpointMBeanInfo).isNotNull();
......
...@@ -26,11 +26,11 @@ import org.junit.Rule; ...@@ -26,11 +26,11 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation; import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration; import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration;
......
...@@ -23,6 +23,7 @@ import java.util.Map; ...@@ -23,6 +23,7 @@ import java.util.Map;
import org.assertj.core.api.Condition; import org.assertj.core.api.Condition;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.actuate.endpoint.DefaultEnablement;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
...@@ -59,7 +60,8 @@ public class EndpointLinksResolverTests { ...@@ -59,7 +60,8 @@ public class EndpointLinksResolverTests {
public void resolvedLinksContainsALinkForEachEndpointOperation() { public void resolvedLinksContainsALinkForEachEndpointOperation() {
Map<String, Link> links = this.linksResolver Map<String, Link> links = this.linksResolver
.resolveLinks( .resolveLinks(
Arrays.asList(new EndpointInfo<>("alpha", true, Arrays.asList(new EndpointInfo<>("alpha",
DefaultEnablement.ENABLED,
Arrays.asList(operationWithPath("/alpha", "alpha"), Arrays.asList(operationWithPath("/alpha", "alpha"),
operationWithPath("/alpha/{name}", operationWithPath("/alpha/{name}",
"alpha-name")))), "alpha-name")))),
......
...@@ -32,11 +32,11 @@ import org.junit.Rule; ...@@ -32,11 +32,11 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.boot.actuate.endpoint.EndpointExposure;
import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationInvoker;
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation; import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector; import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
......
...@@ -367,10 +367,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor ...@@ -367,10 +367,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
if (endpointId == null || "".equals(endpointId)) { if (endpointId == null || "".equals(endpointId)) {
return; // Can't process that endpoint return; // Can't process that endpoint
} }
Boolean enabledByDefault = (Boolean) elementValues.get("enabledByDefault"); Boolean enabledByDefault = determineEnabledByDefault(elementValues.get(
if (enabledByDefault == null) { "defaultEnablement"));
enabledByDefault = Boolean.TRUE;
}
String type = this.typeUtils.getQualifiedName(element); String type = this.typeUtils.getQualifiedName(element);
this.metadataCollector this.metadataCollector
.add(ItemMetadata.newGroup(endpointKey(endpointId), type, type, null)); .add(ItemMetadata.newGroup(endpointKey(endpointId), type, type, null));
...@@ -395,8 +393,21 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor ...@@ -395,8 +393,21 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor
endpointKey(endpointId + ".web"), "enabled", Boolean.class.getName(), endpointKey(endpointId + ".web"), "enabled", Boolean.class.getName(),
type, null, String.format("Expose the %s endpoint as a Web endpoint.", type, null, String.format("Expose the %s endpoint as a Web endpoint.",
endpointId), endpointId),
false, null)); enabledByDefault, null));
}
}
private Boolean determineEnabledByDefault(Object defaultEnablement) {
if (defaultEnablement != null) {
String value = String.valueOf(defaultEnablement);
if ("ENABLED".equals(value)) {
return true;
}
if ("DISABLED".equals(value)) {
return false;
}
} }
return null;
} }
private String endpointKey(String suffix) { private String endpointKey(String suffix) {
......
...@@ -38,6 +38,7 @@ import org.springframework.boot.configurationprocessor.metadata.Metadata; ...@@ -38,6 +38,7 @@ import org.springframework.boot.configurationprocessor.metadata.Metadata;
import org.springframework.boot.configurationprocessor.metadata.TestJsonConverter; import org.springframework.boot.configurationprocessor.metadata.TestJsonConverter;
import org.springframework.boot.configurationsample.endpoint.CustomPropertiesEndpoint; import org.springframework.boot.configurationsample.endpoint.CustomPropertiesEndpoint;
import org.springframework.boot.configurationsample.endpoint.DisabledEndpoint; import org.springframework.boot.configurationsample.endpoint.DisabledEndpoint;
import org.springframework.boot.configurationsample.endpoint.EnabledEndpoint;
import org.springframework.boot.configurationsample.endpoint.OnlyJmxEndpoint; import org.springframework.boot.configurationsample.endpoint.OnlyJmxEndpoint;
import org.springframework.boot.configurationsample.endpoint.OnlyWebEndpoint; import org.springframework.boot.configurationsample.endpoint.OnlyWebEndpoint;
import org.springframework.boot.configurationsample.endpoint.SimpleEndpoint; import org.springframework.boot.configurationsample.endpoint.SimpleEndpoint;
...@@ -538,9 +539,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -538,9 +539,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = compile(SimpleEndpoint.class); ConfigurationMetadata metadata = compile(SimpleEndpoint.class);
assertThat(metadata).has( assertThat(metadata).has(
Metadata.withGroup("endpoints.simple").fromSource(SimpleEndpoint.class)); Metadata.withGroup("endpoints.simple").fromSource(SimpleEndpoint.class));
assertThat(metadata).has(enabledFlag("simple", true)); assertThat(metadata).has(enabledFlag("simple", null));
assertThat(metadata).has(jmxEnabledFlag("simple", true)); assertThat(metadata).has(jmxEnabledFlag("simple", null));
assertThat(metadata).has(webEnabledFlag("simple", false)); assertThat(metadata).has(webEnabledFlag("simple", null));
assertThat(metadata).has(cacheTtl("simple")); assertThat(metadata).has(cacheTtl("simple"));
assertThat(metadata.getItems()).hasSize(5); assertThat(metadata.getItems()).hasSize(5);
} }
...@@ -557,6 +558,18 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -557,6 +558,18 @@ public class ConfigurationMetadataAnnotationProcessorTests {
assertThat(metadata.getItems()).hasSize(5); assertThat(metadata.getItems()).hasSize(5);
} }
@Test
public void enabledEndpoint() throws IOException {
ConfigurationMetadata metadata = compile(EnabledEndpoint.class);
assertThat(metadata).has(Metadata.withGroup("endpoints.enabled")
.fromSource(EnabledEndpoint.class));
assertThat(metadata).has(enabledFlag("enabled", true));
assertThat(metadata).has(jmxEnabledFlag("enabled", true));
assertThat(metadata).has(webEnabledFlag("enabled", true));
assertThat(metadata).has(cacheTtl("enabled"));
assertThat(metadata.getItems()).hasSize(5);
}
@Test @Test
public void customPropertiesEndpoint() throws IOException { public void customPropertiesEndpoint() throws IOException {
ConfigurationMetadata metadata = compile(CustomPropertiesEndpoint.class); ConfigurationMetadata metadata = compile(CustomPropertiesEndpoint.class);
...@@ -564,9 +577,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -564,9 +577,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
.fromSource(CustomPropertiesEndpoint.class)); .fromSource(CustomPropertiesEndpoint.class));
assertThat(metadata).has(Metadata.withProperty("endpoints.customprops.name") assertThat(metadata).has(Metadata.withProperty("endpoints.customprops.name")
.ofType(String.class).withDefaultValue("test")); .ofType(String.class).withDefaultValue("test"));
assertThat(metadata).has(enabledFlag("customprops", true)); assertThat(metadata).has(enabledFlag("customprops", null));
assertThat(metadata).has(jmxEnabledFlag("customprops", true)); assertThat(metadata).has(jmxEnabledFlag("customprops", null));
assertThat(metadata).has(webEnabledFlag("customprops", false)); assertThat(metadata).has(webEnabledFlag("customprops", null));
assertThat(metadata).has(cacheTtl("customprops")); assertThat(metadata).has(cacheTtl("customprops"));
assertThat(metadata.getItems()).hasSize(6); assertThat(metadata.getItems()).hasSize(6);
} }
...@@ -576,8 +589,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -576,8 +589,8 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = compile(OnlyJmxEndpoint.class); ConfigurationMetadata metadata = compile(OnlyJmxEndpoint.class);
assertThat(metadata).has( assertThat(metadata).has(
Metadata.withGroup("endpoints.jmx").fromSource(OnlyJmxEndpoint.class)); Metadata.withGroup("endpoints.jmx").fromSource(OnlyJmxEndpoint.class));
assertThat(metadata).has(enabledFlag("jmx", true)); assertThat(metadata).has(enabledFlag("jmx", null));
assertThat(metadata).has(jmxEnabledFlag("jmx", true)); assertThat(metadata).has(jmxEnabledFlag("jmx", null));
assertThat(metadata).has(cacheTtl("jmx")); assertThat(metadata).has(cacheTtl("jmx"));
assertThat(metadata.getItems()).hasSize(4); assertThat(metadata.getItems()).hasSize(4);
} }
...@@ -587,8 +600,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -587,8 +600,8 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = compile(OnlyWebEndpoint.class); ConfigurationMetadata metadata = compile(OnlyWebEndpoint.class);
assertThat(metadata).has( assertThat(metadata).has(
Metadata.withGroup("endpoints.web").fromSource(OnlyWebEndpoint.class)); Metadata.withGroup("endpoints.web").fromSource(OnlyWebEndpoint.class));
assertThat(metadata).has(enabledFlag("web", true)); assertThat(metadata).has(enabledFlag("web", null));
assertThat(metadata).has(webEnabledFlag("web", false)); assertThat(metadata).has(webEnabledFlag("web", null));
assertThat(metadata).has(cacheTtl("web")); assertThat(metadata).has(cacheTtl("web"));
assertThat(metadata.getItems()).hasSize(4); assertThat(metadata.getItems()).hasSize(4);
} }
...@@ -600,13 +613,14 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -600,13 +613,14 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = project.fullBuild(); ConfigurationMetadata metadata = project.fullBuild();
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalEndpoint.class)); .fromSource(IncrementalEndpoint.class));
assertThat(metadata).has(enabledFlag("incremental", true)); assertThat(metadata).has(enabledFlag("incremental", null));
assertThat(metadata).has(jmxEnabledFlag("incremental", true)); assertThat(metadata).has(jmxEnabledFlag("incremental", null));
assertThat(metadata).has(webEnabledFlag("incremental", false)); assertThat(metadata).has(webEnabledFlag("incremental", null));
assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata).has(cacheTtl("incremental"));
assertThat(metadata.getItems()).hasSize(5); assertThat(metadata.getItems()).hasSize(5);
project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"", project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"",
"id = \"incremental\", enabledByDefault = false"); "id = \"incremental\", defaultEnablement = org.springframework.boot."
+ "configurationsample.DefaultEnablement.DISABLED");
metadata = project.incrementalBuild(IncrementalEndpoint.class); metadata = project.incrementalBuild(IncrementalEndpoint.class);
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalEndpoint.class)); .fromSource(IncrementalEndpoint.class));
...@@ -624,9 +638,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -624,9 +638,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = project.fullBuild(); ConfigurationMetadata metadata = project.fullBuild();
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalEndpoint.class)); .fromSource(IncrementalEndpoint.class));
assertThat(metadata).has(enabledFlag("incremental", true)); assertThat(metadata).has(enabledFlag("incremental", null));
assertThat(metadata).has(jmxEnabledFlag("incremental", true)); assertThat(metadata).has(jmxEnabledFlag("incremental", null));
assertThat(metadata).has(webEnabledFlag("incremental", false)); assertThat(metadata).has(webEnabledFlag("incremental", null));
assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata).has(cacheTtl("incremental"));
assertThat(metadata.getItems()).hasSize(5); assertThat(metadata.getItems()).hasSize(5);
project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"", project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"",
...@@ -635,8 +649,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -635,8 +649,8 @@ public class ConfigurationMetadataAnnotationProcessorTests {
metadata = project.incrementalBuild(IncrementalEndpoint.class); metadata = project.incrementalBuild(IncrementalEndpoint.class);
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalEndpoint.class)); .fromSource(IncrementalEndpoint.class));
assertThat(metadata).has(enabledFlag("incremental", true)); assertThat(metadata).has(enabledFlag("incremental", null));
assertThat(metadata).has(webEnabledFlag("incremental", false)); assertThat(metadata).has(webEnabledFlag("incremental", null));
assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata).has(cacheTtl("incremental"));
assertThat(metadata.getItems()).hasSize(4); assertThat(metadata.getItems()).hasSize(4);
} }
...@@ -648,8 +662,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -648,8 +662,8 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = project.fullBuild(); ConfigurationMetadata metadata = project.fullBuild();
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalJmxEndpoint.class)); .fromSource(IncrementalJmxEndpoint.class));
assertThat(metadata).has(enabledFlag("incremental", true)); assertThat(metadata).has(enabledFlag("incremental", null));
assertThat(metadata).has(jmxEnabledFlag("incremental", true)); assertThat(metadata).has(jmxEnabledFlag("incremental", null));
assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata).has(cacheTtl("incremental"));
assertThat(metadata.getItems()).hasSize(4); assertThat(metadata.getItems()).hasSize(4);
project.replaceText(IncrementalJmxEndpoint.class, project.replaceText(IncrementalJmxEndpoint.class,
...@@ -657,29 +671,29 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -657,29 +671,29 @@ public class ConfigurationMetadataAnnotationProcessorTests {
metadata = project.incrementalBuild(IncrementalJmxEndpoint.class); metadata = project.incrementalBuild(IncrementalJmxEndpoint.class);
assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") assertThat(metadata).has(Metadata.withGroup("endpoints.incremental")
.fromSource(IncrementalJmxEndpoint.class)); .fromSource(IncrementalJmxEndpoint.class));
assertThat(metadata).has(enabledFlag("incremental", true)); assertThat(metadata).has(enabledFlag("incremental", null));
assertThat(metadata).has(jmxEnabledFlag("incremental", true)); assertThat(metadata).has(jmxEnabledFlag("incremental", null));
assertThat(metadata).has(webEnabledFlag("incremental", false)); assertThat(metadata).has(webEnabledFlag("incremental", null));
assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata).has(cacheTtl("incremental"));
assertThat(metadata.getItems()).hasSize(5); assertThat(metadata.getItems()).hasSize(5);
} }
private Metadata.MetadataItemCondition enabledFlag(String endpointId, private Metadata.MetadataItemCondition enabledFlag(String endpointId,
boolean defaultValue) { Boolean defaultValue) {
return Metadata.withEnabledFlag("endpoints." + endpointId + ".enabled") return Metadata.withEnabledFlag("endpoints." + endpointId + ".enabled")
.withDefaultValue(defaultValue) .withDefaultValue(defaultValue)
.withDescription(String.format("Enable the %s endpoint.", endpointId)); .withDescription(String.format("Enable the %s endpoint.", endpointId));
} }
private Metadata.MetadataItemCondition jmxEnabledFlag(String endpointId, private Metadata.MetadataItemCondition jmxEnabledFlag(String endpointId,
boolean defaultValue) { Boolean defaultValue) {
return Metadata.withEnabledFlag("endpoints." + endpointId + ".jmx.enabled") return Metadata.withEnabledFlag("endpoints." + endpointId + ".jmx.enabled")
.withDefaultValue(defaultValue).withDescription(String .withDefaultValue(defaultValue).withDescription(String
.format("Expose the %s endpoint as a JMX MBean.", endpointId)); .format("Expose the %s endpoint as a JMX MBean.", endpointId));
} }
private Metadata.MetadataItemCondition webEnabledFlag(String endpointId, private Metadata.MetadataItemCondition webEnabledFlag(String endpointId,
boolean defaultValue) { Boolean defaultValue) {
return Metadata.withEnabledFlag("endpoints." + endpointId + ".web.enabled") return Metadata.withEnabledFlag("endpoints." + endpointId + ".web.enabled")
.withDefaultValue(defaultValue).withDescription(String .withDefaultValue(defaultValue).withDescription(String
.format("Expose the %s endpoint as a Web endpoint.", endpointId)); .format("Expose the %s endpoint as a Web endpoint.", endpointId));
......
/*
* Copyright 2012-2017 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.configurationsample;
public enum DefaultEnablement {
ENABLED, DISABLED, NEUTRAL
}
...@@ -35,7 +35,7 @@ public @interface Endpoint { ...@@ -35,7 +35,7 @@ public @interface Endpoint {
String id(); String id();
boolean enabledByDefault() default true; DefaultEnablement defaultEnablement() default DefaultEnablement.NEUTRAL;
EndpointExposure[] exposure() default {}; EndpointExposure[] exposure() default {};
......
...@@ -16,14 +16,15 @@ ...@@ -16,14 +16,15 @@
package org.springframework.boot.configurationsample.endpoint; package org.springframework.boot.configurationsample.endpoint;
import org.springframework.boot.configurationsample.DefaultEnablement;
import org.springframework.boot.configurationsample.Endpoint; import org.springframework.boot.configurationsample.Endpoint;
/** /**
* An endpoint that is disabled by default. * An endpoint that is disabled unless configured explicitly.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Endpoint(id = "disabled", enabledByDefault = false) @Endpoint(id = "disabled", defaultEnablement = DefaultEnablement.DISABLED)
public class DisabledEndpoint { public class DisabledEndpoint {
} }
/*
* Copyright 2012-2017 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.configurationsample.endpoint;
import org.springframework.boot.configurationsample.DefaultEnablement;
import org.springframework.boot.configurationsample.Endpoint;
/**
* An endpoint that is enabled unless configured explicitly..
*
* @author Stephane Nicoll
*/
@Endpoint(id = "enabled", defaultEnablement = DefaultEnablement.ENABLED)
public class EnabledEndpoint {
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment