diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java index b688a7c346..56f71c3d36 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java @@ -19,9 +19,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint; import java.util.Arrays; import java.util.List; +import org.springframework.boot.actuate.endpoint.EndpointExposure; import org.springframework.boot.actuate.endpoint.OperationParameterMapper; 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.convert.ConversionServiceOperationParameterMapper; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProvider.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProvider.java index 27351d5714..095c227c8e 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProvider.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProvider.java @@ -16,7 +16,8 @@ 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.util.Assert; @@ -42,24 +43,24 @@ public class EndpointEnablementProvider { * Return the {@link EndpointEnablement} of an endpoint with no specific tech * exposure. * @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 */ public EndpointEnablement getEndpointEnablement(String endpointId, - boolean enabledByDefault) { - return getEndpointEnablement(endpointId, enabledByDefault, null); + DefaultEnablement defaultEnablement) { + return getEndpointEnablement(endpointId, defaultEnablement, null); } /** * Return the {@link EndpointEnablement} of an endpoint for a specific tech exposure. * @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} * @return the {@link EndpointEnablement} of that endpoint for the specified * {@link EndpointExposure} */ public EndpointEnablement getEndpointEnablement(String endpointId, - boolean enabledByDefault, EndpointExposure exposure) { + DefaultEnablement defaultEnablement, EndpointExposure exposure) { Assert.hasText(endpointId, "Endpoint id must have a value"); Assert.isTrue(!endpointId.equals("default"), "Endpoint id 'default' is a reserved " @@ -74,10 +75,11 @@ public class EndpointEnablementProvider { } // All endpoints specific attributes have been looked at. Checking default value // for the endpoint - if (!enabledByDefault) { - return getDefaultEndpointEnablement(endpointId, false, exposure); + if (defaultEnablement != DefaultEnablement.NEUTRAL) { + return getDefaultEndpointEnablement(endpointId, + (defaultEnablement == DefaultEnablement.ENABLED), exposure); } - return getGlobalEndpointEnablement(endpointId, enabledByDefault, exposure); + return getGlobalEndpointEnablement(endpointId, defaultEnablement, exposure); } private EndpointEnablement findEnablement(String endpointId, @@ -89,7 +91,7 @@ public class EndpointEnablementProvider { } private EndpointEnablement getGlobalEndpointEnablement(String endpointId, - boolean enabledByDefault, EndpointExposure exposure) { + DefaultEnablement defaultEnablement, EndpointExposure exposure) { EndpointEnablement result = findGlobalEndpointEnablement(exposure); if (result != null) { return result; @@ -98,7 +100,42 @@ public class EndpointEnablementProvider { if (result != null) { 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) { diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointProvider.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointProvider.java index 91d295d653..7b546794fe 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointProvider.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointProvider.java @@ -20,9 +20,9 @@ import java.util.Collection; import java.util.stream.Collectors; 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.Operation; -import org.springframework.boot.actuate.endpoint.annotation.EndpointExposure; import org.springframework.core.env.Environment; /** @@ -61,7 +61,7 @@ public class EndpointProvider { private boolean isEnabled(EndpointInfo endpoint) { return this.endpointEnablementProvider.getEndpointEnablement(endpoint.getId(), - endpoint.isEnabledByDefault(), this.exposure).isEnabled(); + endpoint.getDefaultEnablement(), this.exposure).isEnabled(); } } diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpoint.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpoint.java index ce267d2e38..b8381f5089 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpoint.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpoint.java @@ -22,22 +22,39 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; 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.EndpointExposure; import org.springframework.context.annotation.Conditional; /** * {@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. *

- * If no specific {@code endpoints..*} or {@code endpoints.default.*} properties are - * defined, the condition matches the {@code enabledByDefault} value regardless of the - * specific {@link EndpointExposure}, if any. If any property are set, they are evaluated - * with a sensible order of precedence. + * When an endpoint uses {@link DefaultEnablement#DISABLED}, it will only be enabled if + * {@code endpoint..enabled}, {@code endpoint..jmx.enabled} or + * {@code endpoint..web.enabled} is {@code true}. *

+ * When an endpoint uses {@link DefaultEnablement#ENABLED}, it will be enabled unless + * {@code endpoint..enabled}, {@code endpoint..jmx.enabled} or + * {@code endpoint..web.enabled} is {@code false}. + *

+ * 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..enabled}, {@code endpoint..jmx.enabled} or + * {@code endpoint..web.enabled} has not been set to {@code false}. + *

+ * If any properties are set, they are evaluated from most to least specific, e.g. + * considering a web endpoint with id {@code foo}: + *

    + *
  1. endpoints.foo.web.enabled
  2. + *
  3. endpoints.foo.enabled
  4. + *
  5. endpoints.default.web.enabled
  6. + *
  7. endpoints.default.enabled
  8. + *
* For instance if {@code endpoints.default.enabled} is {@code false} but - * {@code endpoints..enabled} is {@code true}, the condition will match. + * {@code endpoints..enabled} is {@code true}, the condition will match. *

* 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 @@ -53,7 +70,7 @@ import org.springframework.context.annotation.Conditional; * ... * } * - * @Endpoint(id = "my", enabledByDefault = false) + * @Endpoint(id = "my", defaultEnablement = DefaultEnablement.DISABLED) * static class MyEndpoint { ... } * * } diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnEnabledEndpointCondition.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnEnabledEndpointCondition.java index dc5bdbdd72..bb1166215e 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnEnabledEndpointCondition.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnEnabledEndpointCondition.java @@ -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.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.EndpointExposure; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension; import org.springframework.boot.autoconfigure.condition.ConditionMessage; @@ -106,7 +107,7 @@ class OnEnabledEndpointCondition extends SpringBootCondition { } // If both types are set, all exposure technologies are exposed EndpointExposure[] exposures = endpoint.exposure(); - return new EndpointAttributes(endpoint.id(), endpoint.enabledByDefault(), + return new EndpointAttributes(endpoint.id(), endpoint.defaultEnablement(), (exposures.length == 1 ? exposures[0] : null)); } @@ -114,21 +115,23 @@ class OnEnabledEndpointCondition extends SpringBootCondition { private final String id; - private final boolean enabled; + private final DefaultEnablement defaultEnablement; private final EndpointExposure exposure; - EndpointAttributes(String id, boolean enabled, EndpointExposure exposure) { + EndpointAttributes(String id, DefaultEnablement defaultEnablement, + EndpointExposure exposure) { if (!StringUtils.hasText(id)) { throw new IllegalStateException("Endpoint id could not be determined"); } this.id = id; - this.enabled = enabled; + this.defaultEnablement = defaultEnablement; this.exposure = exposure; } public EndpointEnablement getEnablement(EndpointEnablementProvider provider) { - return provider.getEndpointEnablement(this.id, this.enabled, this.exposure); + return provider.getEndpointEnablement(this.id, this.defaultEnablement, + this.exposure); } } diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.java index bced1ed5b4..96abb0650b 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.java @@ -23,9 +23,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.DefaultCachingConfigurationFactory; 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.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.JmxEndpointOperation; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxAnnotationEndpointDiscoverer; diff --git a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProviderTests.java b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProviderTests.java index 9848b2d76a..7320ab5810 100644 --- a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProviderTests.java +++ b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointEnablementProviderTests.java @@ -20,7 +20,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -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.boot.test.util.TestPropertyValues; import org.springframework.mock.env.MockEnvironment; import org.springframework.util.ObjectUtils; @@ -38,306 +39,238 @@ public class EndpointEnablementProviderTests { public ExpectedException thrown = ExpectedException.none(); @Test - public void cannotDetermineEnablementWithEmptyEndpoint() { - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("Endpoint id must have a value"); - getEndpointEnablement(" ", true); + public void defaultEnablementDisabled() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED); + validate(enablement, false, "endpoint 'foo' is disabled by default"); } @Test - public void cannotDetermineEnablementOfEndpointAll() { - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("Endpoint id 'default' is a reserved value and cannot " - + "be used by an endpoint"); - getEndpointEnablement("default", true); + public void defaultEnablementDisabledWithGeneralEnablement() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED, "endpoints.default.enabled=true"); + validate(enablement, false, "endpoint 'foo' is disabled by default"); } @Test - public void generalEnabledByDefault() { - EndpointEnablement enablement = getEndpointEnablement("foo", true); - validate(enablement, true, "endpoint 'foo' is enabled by default"); - } - - @Test - public void generalDisabledViaSpecificProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.foo.enabled=false"); - validate(enablement, false, "found property endpoints.foo.enabled"); - } - - @Test - public void generalDisabledViaGeneralProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=false"); - validate(enablement, false, "found property endpoints.default.enabled"); + public void defaultEnablementDisabledWithGeneralTechEnablement() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED, EndpointExposure.WEB, + "endpoints.default.web.enabled=true"); + validate(enablement, false, "endpoint 'foo' (web) is disabled by default"); } @Test - public void generalEnabledOverrideViaSpecificProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=false", "endpoints.foo.enabled=true"); + public void defaultEnablementDisabledWithOverride() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED, "endpoints.foo.enabled=true"); validate(enablement, true, "found property endpoints.foo.enabled"); } @Test - public void generalEnabledOverrideViaSpecificWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.foo.enabled=false", "endpoints.foo.web.enabled=true"); + public void defaultEnablementDisabledWithTechOverride() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED, EndpointExposure.WEB, + "endpoints.foo.web.enabled=true"); validate(enablement, true, "found property endpoints.foo.web.enabled"); } @Test - public void generalEnabledOverrideViaSpecificJmxProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.foo.enabled=false", "endpoints.foo.jmx.enabled=true"); - validate(enablement, true, "found property endpoints.foo.jmx.enabled"); - } - - @Test - public void generalEnabledOverrideViaSpecificAnyProperty() { - validate(getEndpointEnablement("foo", true, "endpoints.foo.enabled=false", - "endpoints.foo.web.enabled=false", "endpoints.foo.jmx.enabled=true"), - true, "found property endpoints.foo.jmx.enabled"); - } - - @Test - public void generalEnabledOverrideViaGeneralWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=false", "endpoints.default.web.enabled=true"); - validate(enablement, true, "found property endpoints.default.web.enabled"); - } - - @Test - public void generalEnabledOverrideViaGeneralJmxProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=false", "endpoints.default.jmx.enabled=true"); - validate(enablement, true, "found property endpoints.default.jmx.enabled"); - } - - @Test - public void generalEnabledOverrideViaGeneralAnyProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=false", "endpoints.default.web.enabled=false", - "endpoints.default.jmx.enabled=true"); - validate(enablement, true, "found property endpoints.default.jmx.enabled"); - } - - @Test - public void generalDisabledEvenWithEnabledGeneralProperties() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - "endpoints.default.enabled=true", "endpoints.default.web.enabled=true", - "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false"); - validate(enablement, false, "found property endpoints.foo.enabled"); - } - - @Test - public void generalDisabledByDefaultWithAnnotationFlag() { - EndpointEnablement enablement = getEndpointEnablement("bar", false); - validate(enablement, false, "endpoint 'bar' is disabled by default"); - } - - @Test - public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.default.enabled=true"); - validate(enablement, false, "endpoint 'bar' is disabled by default"); - } - - @Test - public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.default.web.enabled=true"); - validate(enablement, false, "endpoint 'bar' is disabled by default"); - } - - @Test - public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralJmxProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.default.jmx.enabled=true"); - validate(enablement, false, "endpoint 'bar' is disabled by default"); + public void defaultEnablementDisabledWithIrrelevantTechOverride() { + EndpointEnablement enablement = getEndpointEnablement("foo", + DefaultEnablement.DISABLED, EndpointExposure.WEB, + "endpoints.foo.jmx.enabled=true"); + validate(enablement, false, "endpoint 'foo' (web) is disabled by default"); } @Test - public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.bar.enabled=true"); - validate(enablement, true, "found property endpoints.bar.enabled"); + public void defaultEnablementEnabled() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED); + validate(enablement, true, "endpoint 'bar' is enabled by default"); } @Test - public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.bar.web.enabled=true"); - validate(enablement, true, "found property endpoints.bar.web.enabled"); + public void defaultEnablementEnabledWithGeneralDisablement() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED, "endpoints.default.enabled=false"); + validate(enablement, true, "endpoint 'bar' is enabled by default"); } @Test - public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificJmxProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.bar.jmx.enabled=true"); - validate(enablement, true, "found property endpoints.bar.jmx.enabled"); + public void defaultEnablementEnabledWithGeneralTechDisablement() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED, EndpointExposure.JMX, + "endpoints.default.jmx.enabled=false"); + validate(enablement, true, "endpoint 'bar' (jmx) is enabled by default"); } @Test - public void generalEnabledOverrideWithAndAnnotationFlagAndAnyProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - "endpoints.bar.web.enabled=false", "endpoints.bar.jmx.enabled=true"); - validate(enablement, true, "found property endpoints.bar.jmx.enabled"); + public void defaultEnablementEnabledWithOverride() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED, "endpoints.bar.enabled=false"); + validate(enablement, false, "found property endpoints.bar.enabled"); } @Test - public void specificEnabledByDefault() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.JMX); - validate(enablement, true, "endpoint 'foo' (jmx) is enabled by default"); + public void defaultEnablementEnabledWithTechOverride() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED, EndpointExposure.JMX, + "endpoints.bar.jmx.enabled=false"); + validate(enablement, false, "found property endpoints.bar.jmx.enabled"); } @Test - public void specificDisabledViaEndpointProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.foo.enabled=false"); - validate(enablement, false, "found property endpoints.foo.enabled"); + public void defaultEnablementEnabledWithIrrelevantTechOverride() { + EndpointEnablement enablement = getEndpointEnablement("bar", + DefaultEnablement.ENABLED, EndpointExposure.JMX, + "endpoints.bar.web.enabled=false"); + validate(enablement, true, "endpoint 'bar' (jmx) is enabled by default"); } @Test - public void specificDisabledViaTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.foo.web.enabled=false"); - validate(enablement, false, "found property endpoints.foo.web.enabled"); + public void defaultEnablementNeutral() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL); + validate(enablement, true, + "endpoint 'biz' is enabled (default)"); } @Test - public void specificNotDisabledViaUnrelatedTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.JMX, "endpoints.foo.web.enabled=false"); - validate(enablement, true, "endpoint 'foo' (jmx) is enabled by default"); + public void defaultEnablementNeutralWeb() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.WEB); + validate(enablement, false, + "endpoint 'default' (web) is disabled by default"); } @Test - public void specificDisabledViaGeneralProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.JMX, "endpoints.default.enabled=false"); - validate(enablement, false, "found property endpoints.default.enabled"); + public void defaultEnablementNeutralJmx() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX); + validate(enablement, true, + "endpoint 'biz' (jmx) is enabled (default for jmx endpoints)"); } @Test - public void specificEnabledOverrideViaEndpointProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.default.enabled=false", - "endpoints.foo.enabled=true"); - validate(enablement, true, "found property endpoints.foo.enabled"); + public void defaultEnablementNeutralWithGeneralDisablement() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, "endpoints.default.enabled=false"); + validate(enablement, false, + "found property endpoints.default.enabled"); } @Test - public void specificEnabledOverrideViaTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.foo.enabled=false", - "endpoints.foo.web.enabled=true"); - validate(enablement, true, "found property endpoints.foo.web.enabled"); + public void defaultEnablementNeutralWebWithTechDisablement() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.jmx.enabled=false"); + validate(enablement, false, + "found property endpoints.default.jmx.enabled"); } @Test - public void specificEnabledOverrideHasNotEffectWithUnrelatedTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.foo.enabled=false", - "endpoints.foo.jmx.enabled=true"); - validate(enablement, false, "found property endpoints.foo.enabled"); + public void defaultEnablementNeutralTechTakesPrecedence() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.enabled=true", + "endpoints.default.jmx.enabled=false"); + validate(enablement, false, + "found property endpoints.default.jmx.enabled"); } @Test - public void specificEnabledOverrideViaGeneralWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.default.enabled=false", + public void defaultEnablementNeutralWebWithTechEnablement() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.WEB, "endpoints.default.web.enabled=true"); - validate(enablement, true, "found property endpoints.default.web.enabled"); - } - - @Test - public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() { - validate(getEndpointEnablement("foo", true, EndpointExposure.JMX, - "endpoints.default.enabled=false", "endpoints.default.web.enabled=true"), - false, "found property endpoints.default.enabled"); - } - - @Test - public void specificDisabledWithEndpointPropertyEvenWithEnabledGeneralProperties() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.default.enabled=true", - "endpoints.default.web.enabled=true", - "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false"); - validate(enablement, false, "found property endpoints.foo.enabled"); + validate(enablement, true, + "found property endpoints.default.web.enabled"); } @Test - public void specificDisabledWithTechPropertyEvenWithEnabledGeneralProperties() { - EndpointEnablement enablement = getEndpointEnablement("foo", true, - EndpointExposure.WEB, "endpoints.default.enabled=true", - "endpoints.default.web.enabled=true", - "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=true", - "endpoints.foo.web.enabled=false"); - validate(enablement, false, "found property endpoints.foo.web.enabled"); + public void defaultEnablementNeutralWebWithUnrelatedTechDisablement() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.web.enabled=false"); + validate(enablement, true, + "endpoint 'biz' (jmx) is enabled (default for jmx endpoints)"); } @Test - public void specificDisabledByDefaultWithAnnotationFlag() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB); - validate(enablement, false, "endpoint 'bar' (web) is disabled by default"); + public void defaultEnablementNeutralWithOverride() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, "endpoints.biz.enabled=false"); + validate(enablement, false, + "found property endpoints.biz.enabled"); } @Test - public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.default.enabled=true"); - validate(enablement, false, "endpoint 'bar' (web) is disabled by default"); + public void defaultEnablementNeutralWebWithOverride() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.WEB, + "endpoints.biz.web.enabled=true"); + validate(enablement, true, + "found property endpoints.biz.web.enabled"); } @Test - public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralWebProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.default.web.enabled=true"); - validate(enablement, false, "endpoint 'bar' (web) is disabled by default"); + public void defaultEnablementNeutralJmxWithOverride() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.biz.jmx.enabled=false"); + validate(enablement, false, + "found property endpoints.biz.jmx.enabled"); } @Test - public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralJmxProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.default.jmx.enabled=true"); - validate(enablement, false, "endpoint 'bar' (web) is disabled by default"); + public void defaultEnablementNeutralTechTakesPrecedenceOnEverything() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.enabled=false", + "endpoints.default.jmx.enabled=false", + "endpoints.biz.enabled=false", + "endpoints.biz.jmx.enabled=true"); + validate(enablement, true, + "found property endpoints.biz.jmx.enabled"); } @Test - public void specificEnabledOverrideWithAndAnnotationFlagAndEndpointProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.bar.enabled=true"); - validate(enablement, true, "found property endpoints.bar.enabled"); + public void defaultEnablementNeutralSpecificTakesPrecedenceOnDefaults() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.enabled=false", + "endpoints.default.jmx.enabled=false", + "endpoints.biz.enabled=true"); + validate(enablement, true, + "found property endpoints.biz.enabled"); } @Test - public void specificEnabledOverrideWithAndAnnotationFlagAndTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.bar.web.enabled=true"); - validate(enablement, true, "found property endpoints.bar.web.enabled"); - } - - @Test - public void specificEnabledOverrideWithAndAnnotationFlagHasNoEffectWithUnrelatedTechProperty() { - EndpointEnablement enablement = getEndpointEnablement("bar", false, - EndpointExposure.WEB, "endpoints.bar.jmx.enabled=true"); - validate(enablement, false, "endpoint 'bar' (web) is disabled by default"); + public void defaultEnablementNeutralDefaultTechTakesPrecedenceOnGeneralDefault() { + EndpointEnablement enablement = getEndpointEnablement("biz", + DefaultEnablement.NEUTRAL, EndpointExposure.JMX, + "endpoints.default.enabled=false", + "endpoints.default.jmx.enabled=true"); + validate(enablement, true, + "found property endpoints.default.jmx.enabled"); } - private EndpointEnablement getEndpointEnablement(String id, boolean enabledByDefault, - String... environment) { + private EndpointEnablement getEndpointEnablement(String id, + DefaultEnablement enabledByDefault, String... environment) { return getEndpointEnablement(id, enabledByDefault, null, environment); } - private EndpointEnablement getEndpointEnablement(String id, boolean enabledByDefault, - EndpointExposure exposure, String... environment) { + private EndpointEnablement getEndpointEnablement(String id, + DefaultEnablement enabledByDefault, EndpointExposure exposure, + String... environment) { MockEnvironment env = new MockEnvironment(); TestPropertyValues.of(environment).applyTo(env); EndpointEnablementProvider provider = new EndpointEnablementProvider(env); - return provider.getEndpointEnablement(id, enabledByDefault, exposure); + if (exposure != null) { + return provider.getEndpointEnablement(id, enabledByDefault, exposure); + } + return provider.getEndpointEnablement(id, enabledByDefault); } private void validate(EndpointEnablement enablement, boolean enabled, diff --git a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpointTests.java b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpointTests.java index 0c9f7c756e..8c3ccea6f8 100644 --- a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpointTests.java +++ b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnEnabledEndpointTests.java @@ -18,8 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition; 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.EndpointExposure; import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointExtension; import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -297,7 +298,7 @@ public class ConditionalOnEnabledEndpointTests { } @Endpoint(id = "bar", exposure = { EndpointExposure.WEB, - EndpointExposure.JMX }, enabledByDefault = false) + EndpointExposure.JMX }, defaultEnablement = DefaultEnablement.DISABLED) static class BarEndpoint { } diff --git a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/DefaultEndpointPathProviderTests.java b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/DefaultEndpointPathProviderTests.java index 14ab4d1ed1..eb47289bbd 100644 --- a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/DefaultEndpointPathProviderTests.java +++ b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/DefaultEndpointPathProviderTests.java @@ -27,6 +27,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider; 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.web.WebEndpointOperation; @@ -82,8 +83,10 @@ public class DefaultEndpointPathProviderTests { private DefaultEndpointPathProvider createProvider(String contextPath) { Collection> endpoints = new ArrayList<>(); - endpoints.add(new EndpointInfo<>("foo", true, Collections.emptyList())); - endpoints.add(new EndpointInfo<>("bar", true, Collections.emptyList())); + endpoints.add(new EndpointInfo<>("foo", DefaultEnablement.ENABLED, + Collections.emptyList())); + endpoints.add(new EndpointInfo<>("bar", DefaultEnablement.ENABLED, + Collections.emptyList())); given(this.endpointProvider.getEndpoints()).willReturn(endpoints); ManagementServerProperties managementServerProperties = new ManagementServerProperties(); managementServerProperties.setContextPath(contextPath); diff --git a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/RequestMappingEndpointTests.java b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/RequestMappingEndpointTests.java index 79894b1166..1c6bbfcaf0 100644 --- a/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/RequestMappingEndpointTests.java +++ b/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/RequestMappingEndpointTests.java @@ -21,6 +21,7 @@ import java.util.Map; import org.junit.Test; +import org.springframework.boot.actuate.endpoint.DefaultEnablement; import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.web.OperationRequestPredicate; @@ -140,8 +141,8 @@ public class RequestMappingEndpointTests { (arguments) -> "Invoked", true, requestPredicate, "test"); WebMvcEndpointHandlerMapping mapping = new WebMvcEndpointHandlerMapping( new EndpointMapping("application"), - Collections.singleton(new EndpointInfo<>("test", true, - Collections.singleton(operation)))); + Collections.singleton(new EndpointInfo<>("test", + DefaultEnablement.ENABLED, Collections.singleton(operation)))); mapping.setApplicationContext(new StaticApplicationContext()); mapping.afterPropertiesSet(); return mapping; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/ShutdownEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/ShutdownEndpoint.java index 88fc92ab58..a9da05e5a3 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/ShutdownEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/ShutdownEndpoint.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.Map; 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.WriteOperation; import org.springframework.context.ApplicationContext; @@ -34,7 +35,7 @@ import org.springframework.context.ConfigurableApplicationContext; * @author Andy Wilkinson * @since 2.0.0 */ -@Endpoint(id = "shutdown", enabledByDefault = false) +@Endpoint(id = "shutdown", defaultEnablement = DefaultEnablement.DISABLED) public class ShutdownEndpoint implements ApplicationContextAware { private static final Map NO_CONTEXT_MESSAGE = Collections diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DefaultEnablement.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DefaultEnablement.java new file mode 100644 index 0000000000..d8ca91b696 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/DefaultEnablement.java @@ -0,0 +1,42 @@ +/* + * 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 + +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointExposure.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointExposure.java similarity index 88% rename from spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointExposure.java rename to spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointExposure.java index 937d28c86e..70beac4740 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointExposure.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointExposure.java @@ -14,10 +14,10 @@ * 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 * @since 2.0.0 diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointInfo.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointInfo.java index 139fcab489..caf34ca71a 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointInfo.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointInfo.java @@ -29,7 +29,7 @@ public class EndpointInfo { private final String id; - private final boolean enabledByDefault; + private final DefaultEnablement defaultEnablement; private final Collection operations; @@ -37,12 +37,13 @@ public class EndpointInfo { * Creates a new {@code EndpointInfo} describing an endpoint with the given {@code id} * and {@code operations}. * @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 */ - public EndpointInfo(String id, boolean enabledByDefault, Collection operations) { + public EndpointInfo(String id, DefaultEnablement defaultEnablement, + Collection operations) { this.id = id; - this.enabledByDefault = enabledByDefault; + this.defaultEnablement = defaultEnablement; this.operations = operations; } @@ -55,11 +56,11 @@ public class EndpointInfo { } /** - * Returns whether or not this endpoint is enabled by default. - * @return {@code true} if it is enabled by default, otherwise {@code false} + * Return the {@link DefaultEnablement} of the endpoint. + * @return the default enablement */ - public boolean isEnabledByDefault() { - return this.enabledByDefault; + public DefaultEnablement getDefaultEnablement() { + return this.defaultEnablement; } /** diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/AnnotationEndpointDiscoverer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/AnnotationEndpointDiscoverer.java index 82cfb07e69..5a2707e0ed 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/AnnotationEndpointDiscoverer.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/AnnotationEndpointDiscoverer.java @@ -29,7 +29,9 @@ import java.util.function.Consumer; import java.util.function.Function; 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.EndpointExposure; import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.Operation; import org.springframework.boot.actuate.endpoint.OperationType; @@ -117,9 +119,10 @@ public abstract class AnnotationEndpointDiscoverer private EndpointInfo createEndpointInfo(String beanName, Class beanType, AnnotationAttributes attributes) { String id = attributes.getString("id"); - boolean enabledByDefault = attributes.getBoolean("enabledByDefault"); + DefaultEnablement defaultEnablement = (DefaultEnablement) attributes.get( + "defaultEnablement"); Map operations = discoverOperations(id, beanName, beanType); - return new EndpointInfo<>(id, enabledByDefault, operations.values()); + return new EndpointInfo<>(id, defaultEnablement, operations.values()); } private Map, EndpointExtensionInfo> discoverExtensions( @@ -192,7 +195,7 @@ public abstract class AnnotationEndpointDiscoverer .put(this.operationKeyFactory.apply(operation), operation); endpoint.getOperations().forEach(consumer); extension.getOperations().forEach(consumer); - return new EndpointInfo<>(endpoint.getId(), endpoint.isEnabledByDefault(), + return new EndpointInfo<>(endpoint.getId(), endpoint.getDefaultEnablement(), operations.values()); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/Endpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/Endpoint.java index 2204e30d01..2b36b0a411 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/Endpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/Endpoint.java @@ -22,14 +22,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; 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. * * @author Andy Wilkinson * @since 2.0.0 - * @see EndpointDiscoverer + * @see AnnotationEndpointDiscoverer */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @@ -50,9 +51,10 @@ public @interface Endpoint { EndpointExposure[] exposure() default {}; /** - * Whether or not the endpoint is enabled by default. - * @return {@code true} if the endpoint is enabled by default, otherwise {@code false} + * Defines the {@link DefaultEnablement} of the endpoint. By default, the endpoint's + * enablement defaults to the "default" settings. + * @return the default enablement */ - boolean enabledByDefault() default true; + DefaultEnablement defaultEnablement() default DefaultEnablement.NEUTRAL; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscoverer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscoverer.java index 8e6c1cddd3..f4b7e31ef2 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscoverer.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscoverer.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.function.Supplier; 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.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationParameterMapper; @@ -33,7 +34,6 @@ import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer; 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.CachingConfigurationFactory; import org.springframework.boot.actuate.endpoint.cache.CachingOperationInvoker; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/WebAnnotationEndpointDiscoverer.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/WebAnnotationEndpointDiscoverer.java index b4a8a386bd..b8d4fc5594 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/WebAnnotationEndpointDiscoverer.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/WebAnnotationEndpointDiscoverer.java @@ -27,6 +27,7 @@ import java.util.stream.Stream; import org.reactivestreams.Publisher; +import org.springframework.boot.actuate.endpoint.EndpointExposure; import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationParameterMapper; @@ -34,7 +35,6 @@ import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.annotation.AnnotationEndpointDiscoverer; 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.cache.CachingConfiguration; import org.springframework.boot.actuate.endpoint.cache.CachingConfigurationFactory; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/logger/LogFileWebEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/logger/LogFileWebEndpoint.java index 7f4b2b799c..fb8f5d3787 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/logger/LogFileWebEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/logger/LogFileWebEndpoint.java @@ -21,8 +21,8 @@ import java.io.File; import org.apache.commons.logging.Log; 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.EndpointExposure; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.logging.LogFile; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java index 8e806f7e4e..4d61f05431 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java @@ -36,8 +36,8 @@ import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.logging.Log; 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.EndpointExposure; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanInfoAssemblerTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanInfoAssemblerTests.java index 5739430b13..0abc746b46 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanInfoAssemblerTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanInfoAssemblerTests.java @@ -25,6 +25,7 @@ import javax.management.MBeanParameterInfo; import org.junit.Test; +import org.springframework.boot.actuate.endpoint.DefaultEnablement; import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.OperationInvoker; import org.springframework.boot.actuate.endpoint.OperationType; @@ -47,8 +48,8 @@ public class EndpointMBeanInfoAssemblerTests { JmxEndpointOperation operation = new JmxEndpointOperation(OperationType.READ, new DummyOperationInvoker(), "getAll", Object.class, "Test operation", Collections.emptyList()); - EndpointInfo endpoint = new EndpointInfo<>("test", true, - Collections.singletonList(operation)); + EndpointInfo endpoint = new EndpointInfo<>("test", + DefaultEnablement.ENABLED, Collections.singletonList(operation)); EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler .createEndpointMBeanInfo(endpoint); assertThat(endpointMBeanInfo).isNotNull(); @@ -77,8 +78,8 @@ public class EndpointMBeanInfoAssemblerTests { new DummyOperationInvoker(), "update", Object.class, "Update operation", Collections.singletonList(new JmxEndpointOperationParameterInfo("test", String.class, "Test argument"))); - EndpointInfo endpoint = new EndpointInfo<>("another", true, - Collections.singletonList(operation)); + EndpointInfo endpoint = new EndpointInfo<>("another", + DefaultEnablement.ENABLED, Collections.singletonList(operation)); EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler .createEndpointMBeanInfo(endpoint); assertThat(endpointMBeanInfo).isNotNull(); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscovererTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscovererTests.java index 91a1321e6d..56eb37077d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscovererTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/annotation/JmxAnnotationEndpointDiscovererTests.java @@ -26,11 +26,11 @@ import org.junit.Rule; import org.junit.Test; 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.ReflectiveOperationInvoker; import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation; 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.WriteOperation; import org.springframework.boot.actuate.endpoint.cache.CachingConfiguration; diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/EndpointLinksResolverTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/EndpointLinksResolverTests.java index d1ed8f5424..a400ebf5e9 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/EndpointLinksResolverTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/EndpointLinksResolverTests.java @@ -23,6 +23,7 @@ import java.util.Map; import org.assertj.core.api.Condition; import org.junit.Test; +import org.springframework.boot.actuate.endpoint.DefaultEnablement; import org.springframework.boot.actuate.endpoint.EndpointInfo; import org.springframework.boot.actuate.endpoint.OperationType; @@ -59,7 +60,8 @@ public class EndpointLinksResolverTests { public void resolvedLinksContainsALinkForEachEndpointOperation() { Map links = this.linksResolver .resolveLinks( - Arrays.asList(new EndpointInfo<>("alpha", true, + Arrays.asList(new EndpointInfo<>("alpha", + DefaultEnablement.ENABLED, Arrays.asList(operationWithPath("/alpha", "alpha"), operationWithPath("/alpha/{name}", "alpha-name")))), diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/WebAnnotationEndpointDiscovererTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/WebAnnotationEndpointDiscovererTests.java index 933b909274..c1e2eaaaf0 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/WebAnnotationEndpointDiscovererTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/WebAnnotationEndpointDiscovererTests.java @@ -32,11 +32,11 @@ import org.junit.Rule; import org.junit.Test; 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.OperationInvoker; import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation; 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.Selector; import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 763e04b995..6ad1a1556f 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -1074,28 +1074,28 @@ content into your application; rather pick only the properties that you need. # AUDIT EVENTS ENDPOINT ({sc-spring-boot-actuator}/endpoint/AuditEventsEndpoint.{sc-ext}[AuditEventsEndpoint]) endpoints.auditevents.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.auditevents.enabled=true # Enable the auditevents endpoint. - endpoints.auditevents.jmx.enabled=true # Expose the auditevents endpoint as a JMX MBean. - endpoints.auditevents.web.enabled=false # Expose the auditevents endpoint as a Web endpoint. + endpoints.auditevents.enabled= # Enable the auditevents endpoint. + endpoints.auditevents.jmx.enabled= # Expose the auditevents endpoint as a JMX MBean. + endpoints.auditevents.web.enabled= # Expose the auditevents endpoint as a Web endpoint. # AUTO-CONFIGURATION REPORT ENDPOINT ({sc-spring-boot-actuator}/endpoint/AutoConfigurationReportEndpoint.{sc-ext}[AutoConfigurationReportEndpoint]) endpoints.autoconfig.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.autoconfig.enabled=true # Enable the autoconfig endpoint. - endpoints.autoconfig.jmx.enabled=true # Expose the autoconfig endpoint as a JMX MBean. - endpoints.autoconfig.web.enabled=false # Expose the autoconfig endpoint as a Web endpoint. + endpoints.autoconfig.enabled= # Enable the autoconfig endpoint. + endpoints.autoconfig.jmx.enabled= # Expose the autoconfig endpoint as a JMX MBean. + endpoints.autoconfig.web.enabled= # Expose the autoconfig endpoint as a Web endpoint. # BEANS ENDPOINT ({sc-spring-boot-actuator}/endpoint/BeansEndpoint.{sc-ext}[BeansEndpoint]) endpoints.beans.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.beans.enabled=true # Enable the beans endpoint. - endpoints.beans.jmx.enabled=true # Expose the beans endpoint as a JMX MBean. - endpoints.beans.web.enabled=false # Expose the beans endpoint as a Web endpoint. + endpoints.beans.enabled= # Enable the beans endpoint. + endpoints.beans.jmx.enabled= # Expose the beans endpoint as a JMX MBean. + endpoints.beans.web.enabled= # Expose the beans endpoint as a Web endpoint. # CONFIGURATION PROPERTIES REPORT ENDPOINT ({sc-spring-boot-actuator}/endpoint/ConfigurationPropertiesReportEndpoint.{sc-ext}[ConfigurationPropertiesReportEndpoint]) endpoints.configprops.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.configprops.enabled=true # Enable the configprops endpoint. - endpoints.configprops.jmx.enabled=true # Expose the configprops endpoint as a JMX MBean. + endpoints.configprops.enabled= # Enable the configprops endpoint. + endpoints.configprops.jmx.enabled= # Expose the configprops endpoint as a JMX MBean. endpoints.configprops.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. - endpoints.configprops.web.enabled=false # Expose the configprops endpoint as a Web endpoint. + endpoints.configprops.web.enabled= # Expose the configprops endpoint as a Web endpoint. # ENDPOINT DEFAULT SETTINGS endpoints.default.enabled=true # Enable all endpoints by default. @@ -1104,63 +1104,63 @@ content into your application; rather pick only the properties that you need. # ENVIRONMENT ENDPOINT ({sc-spring-boot-actuator}/endpoint/EnvironmentEndpoint.{sc-ext}[EnvironmentEndpoint]) endpoints.env.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.env.enabled=true # Enable the env endpoint. - endpoints.env.jmx.enabled=true # Expose the env endpoint as a JMX MBean. + endpoints.env.enabled= # Enable the env endpoint. + endpoints.env.jmx.enabled= # Expose the env endpoint as a JMX MBean. endpoints.env.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. - endpoints.env.web.enabled=false # Expose the env endpoint as a Web endpoint. + endpoints.env.web.enabled= # Expose the env endpoint as a Web endpoint. # FLYWAY ENDPOINT ({sc-spring-boot-actuator}/endpoint/FlywayEndpoint.{sc-ext}[FlywayEndpoint]) endpoints.flyway.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.flyway.enabled=true # Enable the flyway endpoint. - endpoints.flyway.jmx.enabled=true # Expose the flyway endpoint as a JMX MBean. - endpoints.flyway.web.enabled=false # Expose the flyway endpoint as a Web endpoint. + endpoints.flyway.enabled= # Enable the flyway endpoint. + endpoints.flyway.jmx.enabled= # Expose the flyway endpoint as a JMX MBean. + endpoints.flyway.web.enabled= # Expose the flyway endpoint as a Web endpoint. # HEALTH ENDPOINT ({sc-spring-boot-actuator}/endpoint/HealthEndpoint.{sc-ext}[HealthEndpoint]) endpoints.health.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.health.enabled=true # Enable the health endpoint. - endpoints.health.jmx.enabled=true # Expose the health endpoint as a JMX MBean. - endpoints.health.web.enabled=false # Expose the health endpoint as a Web endpoint. + endpoints.health.enabled= # Enable the health endpoint. + endpoints.health.jmx.enabled= # Expose the health endpoint as a JMX MBean. + endpoints.health.web.enabled= # Expose the health endpoint as a Web endpoint. # HEAP DUMP ENDPOINT ({sc-spring-boot-actuator}/endpoint/web/HeapDumpWebEndpoint.{sc-ext}[HeapDumpWebEndpoint]) endpoints.heapdump.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.heapdump.enabled=true # Enable the heapdump endpoint. - endpoints.heapdump.web.enabled=false # Expose the heapdump endpoint as a Web endpoint. + endpoints.heapdump.enabled= # Enable the heapdump endpoint. + endpoints.heapdump.web.enabled= # Expose the heapdump endpoint as a Web endpoint. # INFO ENDPOINT ({sc-spring-boot-actuator}/endpoint/InfoEndpoint.{sc-ext}[InfoEndpoint]) endpoints.info.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.info.enabled=true # Enable the info endpoint. - endpoints.info.jmx.enabled=true # Expose the info endpoint as a JMX MBean. - endpoints.info.web.enabled=false # Expose the info endpoint as a Web endpoint. + endpoints.info.enabled= # Enable the info endpoint. + endpoints.info.jmx.enabled= # Expose the info endpoint as a JMX MBean. + endpoints.info.web.enabled= # Expose the info endpoint as a Web endpoint. # LIQUIBASE ENDPOINT ({sc-spring-boot-actuator}/endpoint/LiquibaseEndpoint.{sc-ext}[LiquibaseEndpoint]) endpoints.liquibase.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.liquibase.enabled=true # Enable the liquibase endpoint. - endpoints.liquibase.jmx.enabled=true # Expose the liquibase endpoint as a JMX MBean. - endpoints.liquibase.web.enabled=false # Expose the liquibase endpoint as a Web endpoint. + endpoints.liquibase.enabled= # Enable the liquibase endpoint. + endpoints.liquibase.jmx.enabled= # Expose the liquibase endpoint as a JMX MBean. + endpoints.liquibase.web.enabled= # Expose the liquibase endpoint as a Web endpoint. # LOG FILE ENDPOINT ({sc-spring-boot-actuator}/endpoint/web/LogFileWebEndpoint.{sc-ext}[LogFileWebEndpoint]) endpoints.logfile.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.logfile.enabled=true # Enable the logfile endpoint. + endpoints.logfile.enabled= # Enable the logfile endpoint. endpoints.logfile.external-file= # External Logfile to be accessed. Can be used if the logfile is written by output redirect and not by the logging system itself. - endpoints.logfile.web.enabled=false # Expose the logfile endpoint as a Web endpoint. + endpoints.logfile.web.enabled= # Expose the logfile endpoint as a Web endpoint. # LOGGERS ENDPOINT ({sc-spring-boot-actuator}/endpoint/LoggersEndpoint.{sc-ext}[LoggersEndpoint]) endpoints.loggers.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.loggers.enabled=true # Enable the loggers endpoint. - endpoints.loggers.jmx.enabled=true # Expose the loggers endpoint as a JMX MBean. - endpoints.loggers.web.enabled=false # Expose the loggers endpoint as a Web endpoint. + endpoints.loggers.enabled= # Enable the loggers endpoint. + endpoints.loggers.jmx.enabled= # Expose the loggers endpoint as a JMX MBean. + endpoints.loggers.web.enabled= # Expose the loggers endpoint as a Web endpoint. # REQUEST MAPPING ENDPOINT ({sc-spring-boot-actuator}/endpoint/RequestMappingEndpoint.{sc-ext}[RequestMappingEndpoint]) endpoints.mappings.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.mappings.enabled=true # Enable the mappings endpoint. - endpoints.mappings.jmx.enabled=true # Expose the mappings endpoint as a JMX MBean. - endpoints.mappings.web.enabled=false # Expose the mappings endpoint as a Web endpoint. + endpoints.mappings.enabled= # Enable the mappings endpoint. + endpoints.mappings.jmx.enabled= # Expose the mappings endpoint as a JMX MBean. + endpoints.mappings.web.enabled= # Expose the mappings endpoint as a Web endpoint. # METRICS ENDPOINT ({sc-spring-boot-actuator}/endpoint/MetricsEndpoint.{sc-ext}[MetricsEndpoint]) endpoints.metrics.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.metrics.enabled=true # Enable the metrics endpoint. - endpoints.metrics.jmx.enabled=true # Expose the metrics endpoint as a JMX MBean. - endpoints.metrics.web.enabled=false # Expose the metrics endpoint as a Web endpoint. + endpoints.metrics.enabled= # Enable the metrics endpoint. + endpoints.metrics.jmx.enabled= # Expose the metrics endpoint as a JMX MBean. + endpoints.metrics.web.enabled= # Expose the metrics endpoint as a Web endpoint. # SHUTDOWN ENDPOINT ({sc-spring-boot-actuator}/endpoint/ShutdownEndpoint.{sc-ext}[ShutdownEndpoint]) endpoints.shutdown.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. @@ -1170,21 +1170,21 @@ content into your application; rather pick only the properties that you need. # STATUS ENDPOINT ({sc-spring-boot-actuator}/endpoint/StatusEndpoint.{sc-ext}[StatusEndpoint]) endpoints.status.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.status.enabled=true # Enable the status endpoint. - endpoints.status.jmx.enabled=true # Expose the status endpoint as a JMX MBean. - endpoints.status.web.enabled=false # Expose the status endpoint as a Web endpoint. + endpoints.status.enabled= # Enable the status endpoint. + endpoints.status.jmx.enabled= # Expose the status endpoint as a JMX MBean. + endpoints.status.web.enabled= # Expose the status endpoint as a Web endpoint. # THREAD DUMP ENDPOINT ({sc-spring-boot-actuator}/endpoint/ThreadDumpEndpoint.{sc-ext}[ThreadDumpEndpoint]) endpoints.threaddump.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.threaddump.enabled=true # Enable the threaddump endpoint. - endpoints.threaddump.jmx.enabled=true # Expose the threaddump endpoint as a JMX MBean. - endpoints.threaddump.web.enabled=false # Expose the threaddump endpoint as a Web endpoint. + endpoints.threaddump.enabled= # Enable the threaddump endpoint. + endpoints.threaddump.jmx.enabled= # Expose the threaddump endpoint as a JMX MBean. + endpoints.threaddump.web.enabled= # Expose the threaddump endpoint as a Web endpoint. # TRACE ENDPOINT ({sc-spring-boot-actuator}/endpoint/TraceEndpoint.{sc-ext}[TraceEndpoint]) endpoints.trace.cache.time-to-live=0 # Maximum time in milliseconds that a response can be cached. - endpoints.trace.enabled=true # Enable the trace endpoint. - endpoints.trace.jmx.enabled=true # Expose the trace endpoint as a JMX MBean. - endpoints.trace.web.enabled=false # Expose the trace endpoint as a Web endpoint. + endpoints.trace.enabled= # Enable the trace endpoint. + endpoints.trace.jmx.enabled= # Expose the trace endpoint as a JMX MBean. + endpoints.trace.web.enabled= # Expose the trace endpoint as a Web endpoint. # MANAGEMENT HTTP SERVER ({sc-spring-boot-actuator}/autoconfigure/web/ManagementServerProperties.{sc-ext}[ManagementServerProperties]) management.add-application-context-header=false # Add the "X-Application-Context" HTTP header in each response. diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index 3b0670c54e..9817dd5b3f 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -367,10 +367,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor if (endpointId == null || "".equals(endpointId)) { return; // Can't process that endpoint } - Boolean enabledByDefault = (Boolean) elementValues.get("enabledByDefault"); - if (enabledByDefault == null) { - enabledByDefault = Boolean.TRUE; - } + Boolean enabledByDefault = determineEnabledByDefault(elementValues.get( + "defaultEnablement")); String type = this.typeUtils.getQualifiedName(element); this.metadataCollector .add(ItemMetadata.newGroup(endpointKey(endpointId), type, type, null)); @@ -395,8 +393,21 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor endpointKey(endpointId + ".web"), "enabled", Boolean.class.getName(), type, null, String.format("Expose the %s endpoint as a Web endpoint.", 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) { diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java index 636cce078a..8abd59bd36 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java @@ -38,6 +38,7 @@ import org.springframework.boot.configurationprocessor.metadata.Metadata; import org.springframework.boot.configurationprocessor.metadata.TestJsonConverter; import org.springframework.boot.configurationsample.endpoint.CustomPropertiesEndpoint; 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.OnlyWebEndpoint; import org.springframework.boot.configurationsample.endpoint.SimpleEndpoint; @@ -538,9 +539,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = compile(SimpleEndpoint.class); assertThat(metadata).has( Metadata.withGroup("endpoints.simple").fromSource(SimpleEndpoint.class)); - assertThat(metadata).has(enabledFlag("simple", true)); - assertThat(metadata).has(jmxEnabledFlag("simple", true)); - assertThat(metadata).has(webEnabledFlag("simple", false)); + assertThat(metadata).has(enabledFlag("simple", null)); + assertThat(metadata).has(jmxEnabledFlag("simple", null)); + assertThat(metadata).has(webEnabledFlag("simple", null)); assertThat(metadata).has(cacheTtl("simple")); assertThat(metadata.getItems()).hasSize(5); } @@ -557,6 +558,18 @@ public class ConfigurationMetadataAnnotationProcessorTests { 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 public void customPropertiesEndpoint() throws IOException { ConfigurationMetadata metadata = compile(CustomPropertiesEndpoint.class); @@ -564,9 +577,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { .fromSource(CustomPropertiesEndpoint.class)); assertThat(metadata).has(Metadata.withProperty("endpoints.customprops.name") .ofType(String.class).withDefaultValue("test")); - assertThat(metadata).has(enabledFlag("customprops", true)); - assertThat(metadata).has(jmxEnabledFlag("customprops", true)); - assertThat(metadata).has(webEnabledFlag("customprops", false)); + assertThat(metadata).has(enabledFlag("customprops", null)); + assertThat(metadata).has(jmxEnabledFlag("customprops", null)); + assertThat(metadata).has(webEnabledFlag("customprops", null)); assertThat(metadata).has(cacheTtl("customprops")); assertThat(metadata.getItems()).hasSize(6); } @@ -576,8 +589,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = compile(OnlyJmxEndpoint.class); assertThat(metadata).has( Metadata.withGroup("endpoints.jmx").fromSource(OnlyJmxEndpoint.class)); - assertThat(metadata).has(enabledFlag("jmx", true)); - assertThat(metadata).has(jmxEnabledFlag("jmx", true)); + assertThat(metadata).has(enabledFlag("jmx", null)); + assertThat(metadata).has(jmxEnabledFlag("jmx", null)); assertThat(metadata).has(cacheTtl("jmx")); assertThat(metadata.getItems()).hasSize(4); } @@ -587,8 +600,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = compile(OnlyWebEndpoint.class); assertThat(metadata).has( Metadata.withGroup("endpoints.web").fromSource(OnlyWebEndpoint.class)); - assertThat(metadata).has(enabledFlag("web", true)); - assertThat(metadata).has(webEnabledFlag("web", false)); + assertThat(metadata).has(enabledFlag("web", null)); + assertThat(metadata).has(webEnabledFlag("web", null)); assertThat(metadata).has(cacheTtl("web")); assertThat(metadata.getItems()).hasSize(4); } @@ -600,13 +613,14 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = project.fullBuild(); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalEndpoint.class)); - assertThat(metadata).has(enabledFlag("incremental", true)); - assertThat(metadata).has(jmxEnabledFlag("incremental", true)); - assertThat(metadata).has(webEnabledFlag("incremental", false)); + assertThat(metadata).has(enabledFlag("incremental", null)); + assertThat(metadata).has(jmxEnabledFlag("incremental", null)); + assertThat(metadata).has(webEnabledFlag("incremental", null)); assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata.getItems()).hasSize(5); project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"", - "id = \"incremental\", enabledByDefault = false"); + "id = \"incremental\", defaultEnablement = org.springframework.boot." + + "configurationsample.DefaultEnablement.DISABLED"); metadata = project.incrementalBuild(IncrementalEndpoint.class); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalEndpoint.class)); @@ -624,9 +638,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = project.fullBuild(); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalEndpoint.class)); - assertThat(metadata).has(enabledFlag("incremental", true)); - assertThat(metadata).has(jmxEnabledFlag("incremental", true)); - assertThat(metadata).has(webEnabledFlag("incremental", false)); + assertThat(metadata).has(enabledFlag("incremental", null)); + assertThat(metadata).has(jmxEnabledFlag("incremental", null)); + assertThat(metadata).has(webEnabledFlag("incremental", null)); assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata.getItems()).hasSize(5); project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"", @@ -635,8 +649,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { metadata = project.incrementalBuild(IncrementalEndpoint.class); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalEndpoint.class)); - assertThat(metadata).has(enabledFlag("incremental", true)); - assertThat(metadata).has(webEnabledFlag("incremental", false)); + assertThat(metadata).has(enabledFlag("incremental", null)); + assertThat(metadata).has(webEnabledFlag("incremental", null)); assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata.getItems()).hasSize(4); } @@ -648,8 +662,8 @@ public class ConfigurationMetadataAnnotationProcessorTests { ConfigurationMetadata metadata = project.fullBuild(); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalJmxEndpoint.class)); - assertThat(metadata).has(enabledFlag("incremental", true)); - assertThat(metadata).has(jmxEnabledFlag("incremental", true)); + assertThat(metadata).has(enabledFlag("incremental", null)); + assertThat(metadata).has(jmxEnabledFlag("incremental", null)); assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata.getItems()).hasSize(4); project.replaceText(IncrementalJmxEndpoint.class, @@ -657,29 +671,29 @@ public class ConfigurationMetadataAnnotationProcessorTests { metadata = project.incrementalBuild(IncrementalJmxEndpoint.class); assertThat(metadata).has(Metadata.withGroup("endpoints.incremental") .fromSource(IncrementalJmxEndpoint.class)); - assertThat(metadata).has(enabledFlag("incremental", true)); - assertThat(metadata).has(jmxEnabledFlag("incremental", true)); - assertThat(metadata).has(webEnabledFlag("incremental", false)); + assertThat(metadata).has(enabledFlag("incremental", null)); + assertThat(metadata).has(jmxEnabledFlag("incremental", null)); + assertThat(metadata).has(webEnabledFlag("incremental", null)); assertThat(metadata).has(cacheTtl("incremental")); assertThat(metadata.getItems()).hasSize(5); } private Metadata.MetadataItemCondition enabledFlag(String endpointId, - boolean defaultValue) { + Boolean defaultValue) { return Metadata.withEnabledFlag("endpoints." + endpointId + ".enabled") .withDefaultValue(defaultValue) .withDescription(String.format("Enable the %s endpoint.", endpointId)); } private Metadata.MetadataItemCondition jmxEnabledFlag(String endpointId, - boolean defaultValue) { + Boolean defaultValue) { return Metadata.withEnabledFlag("endpoints." + endpointId + ".jmx.enabled") .withDefaultValue(defaultValue).withDescription(String .format("Expose the %s endpoint as a JMX MBean.", endpointId)); } private Metadata.MetadataItemCondition webEnabledFlag(String endpointId, - boolean defaultValue) { + Boolean defaultValue) { return Metadata.withEnabledFlag("endpoints." + endpointId + ".web.enabled") .withDefaultValue(defaultValue).withDescription(String .format("Expose the %s endpoint as a Web endpoint.", endpointId)); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/DefaultEnablement.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/DefaultEnablement.java new file mode 100644 index 0000000000..8add606a84 --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/DefaultEnablement.java @@ -0,0 +1,22 @@ +/* + * 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 +} diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/Endpoint.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/Endpoint.java index 02eed09a71..056e842487 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/Endpoint.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/Endpoint.java @@ -35,7 +35,7 @@ public @interface Endpoint { String id(); - boolean enabledByDefault() default true; + DefaultEnablement defaultEnablement() default DefaultEnablement.NEUTRAL; EndpointExposure[] exposure() default {}; diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/DisabledEndpoint.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/DisabledEndpoint.java index d3eeb2a048..83932f9f3c 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/DisabledEndpoint.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/DisabledEndpoint.java @@ -16,14 +16,15 @@ package org.springframework.boot.configurationsample.endpoint; +import org.springframework.boot.configurationsample.DefaultEnablement; import org.springframework.boot.configurationsample.Endpoint; /** - * An endpoint that is disabled by default. + * An endpoint that is disabled unless configured explicitly. * * @author Stephane Nicoll */ -@Endpoint(id = "disabled", enabledByDefault = false) +@Endpoint(id = "disabled", defaultEnablement = DefaultEnablement.DISABLED) public class DisabledEndpoint { } diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/EnabledEndpoint.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/EnabledEndpoint.java new file mode 100644 index 0000000000..58a38ccbf5 --- /dev/null +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/endpoint/EnabledEndpoint.java @@ -0,0 +1,30 @@ +/* + * 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 { + +}