diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java index 13fdbe6d39..b1dfb96bba 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java @@ -62,6 +62,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * {@link EmbeddedServletContainer} running on a different port is required. * * @author Dave Syer + * @author Stephane Nicoll * @see EndpointWebMvcAutoConfiguration */ @Configuration @@ -145,9 +146,14 @@ public class EndpointWebMvcChildContextConfiguration { return new ManagementErrorEndpoint(this.errorPath, errorAttributes); } + /** + * Configuration to add {@link HandlerMapping} for {@link MvcEndpoint}s. See + * {@link SecureEndpointHandlerMappingConfiguration} for an extended version that also + * configures the security filter. + */ @Configuration @ConditionalOnMissingClass(WebSecurityConfigurerAdapter.class) - static class EndpointHandlerMappingSimpleConfiguration { + protected static class EndpointHandlerMappingConfiguration { @Autowired(required = false) private List mappingCustomizers; @@ -155,8 +161,12 @@ public class EndpointWebMvcChildContextConfiguration { @Bean public HandlerMapping handlerMapping(MvcEndpoints endpoints, ListableBeanFactory beanFactory) { - - EndpointHandlerMapping mapping = doCreateEndpointHandlerMapping(endpoints, beanFactory); + Set set = new HashSet(endpoints.getEndpoints()); + set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values()); + EndpointHandlerMapping mapping = new EndpointHandlerMapping(set); + // In a child context we definitely want to see the parent endpoints + mapping.setDetectHandlerMethodsInAncestorContexts(true); + postProcessMapping(beanFactory, mapping); if (this.mappingCustomizers != null) { for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) { customizer.customize(mapping); @@ -165,36 +175,31 @@ public class EndpointWebMvcChildContextConfiguration { return mapping; } - protected EndpointHandlerMapping doCreateEndpointHandlerMapping(MvcEndpoints endpoints, - ListableBeanFactory beanFactory) { - Set set = new HashSet(endpoints.getEndpoints()); - set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values()); - EndpointHandlerMapping mapping = new EndpointHandlerMapping(set); - // In a child context we definitely want to see the parent endpoints - mapping.setDetectHandlerMethodsInAncestorContexts(true); - return mapping; + /** + * Hook to allow additional post processing of {@link EndpointHandlerMapping}. + * @param beanFactory the source bean factory + * @param mapping the mapping to customize + */ + protected void postProcessMapping(ListableBeanFactory beanFactory, + EndpointHandlerMapping mapping) { } } + /** + * Extension of {@link EndpointHandlerMappingConfiguration} that also configures the + * security filter. + */ @Configuration @ConditionalOnClass(WebSecurityConfigurerAdapter.class) - static class EndpointHandlerMappingSecurityConfiguration - extends EndpointHandlerMappingSimpleConfiguration { + protected static class SecureEndpointHandlerMappingConfiguration extends + EndpointHandlerMappingConfiguration { @Override - protected EndpointHandlerMapping doCreateEndpointHandlerMapping(MvcEndpoints endpoints, - ListableBeanFactory beanFactory) { - - EndpointHandlerMapping mapping = super.doCreateEndpointHandlerMapping(endpoints, beanFactory); - injectIntoSecurityFilter(beanFactory, mapping); - return mapping; - } - - private void injectIntoSecurityFilter(ListableBeanFactory beanFactory, + protected void postProcessMapping(ListableBeanFactory beanFactory, EndpointHandlerMapping mapping) { - // The parent context has the security filter, so we need to get it injected with - // our EndpointHandlerMapping if we can. + // The parent context has the security filter, so we need to get it injected + // with our EndpointHandlerMapping if we can. if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, ManagementWebSecurityConfigurerAdapter.class).length == 1) { ManagementWebSecurityConfigurerAdapter bean = beanFactory diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java index 4684bb8d3f..56ac8fbb53 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java @@ -92,8 +92,7 @@ public class HealthIndicatorAutoConfigurationTests { public void redisHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(RedisAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.diskspace.enabled:false"); this.context.refresh(); @@ -108,8 +107,7 @@ public class HealthIndicatorAutoConfigurationTests { public void notRedisHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(RedisAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.redis.enabled:false", "management.health.diskspace.enabled:false"); @@ -125,8 +123,8 @@ public class HealthIndicatorAutoConfigurationTests { public void mongoHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(MongoAutoConfiguration.class, - ManagementServerProperties.class, - MongoDataAutoConfiguration.class, HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, MongoDataAutoConfiguration.class, + HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.diskspace.enabled:false"); this.context.refresh(); @@ -141,8 +139,8 @@ public class HealthIndicatorAutoConfigurationTests { public void notMongoHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(MongoAutoConfiguration.class, - ManagementServerProperties.class, - MongoDataAutoConfiguration.class, HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, MongoDataAutoConfiguration.class, + HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.mongo.enabled:false", "management.health.diskspace.enabled:false"); @@ -170,8 +168,7 @@ public class HealthIndicatorAutoConfigurationTests { public void dataSourceHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(EmbeddedDataSourceConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.diskspace.enabled:false"); this.context.refresh(); @@ -186,8 +183,8 @@ public class HealthIndicatorAutoConfigurationTests { public void dataSourceHealthIndicatorWithCustomValidationQuery() { this.context = new AnnotationConfigApplicationContext(); this.context.register(PropertyPlaceholderAutoConfiguration.class, - ManagementServerProperties.class, - DataSourceProperties.class, DataSourceConfig.class, + ManagementServerProperties.class, DataSourceProperties.class, + DataSourceConfig.class, DataSourcePoolMetadataProvidersConfiguration.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, @@ -207,8 +204,7 @@ public class HealthIndicatorAutoConfigurationTests { public void notDataSourceHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(EmbeddedDataSourceConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.db.enabled:false", "management.health.diskspace.enabled:false"); @@ -224,8 +220,7 @@ public class HealthIndicatorAutoConfigurationTests { public void rabbitHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(RabbitAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.diskspace.enabled:false"); this.context.refresh(); @@ -240,8 +235,7 @@ public class HealthIndicatorAutoConfigurationTests { public void notRabbitHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(RabbitAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.rabbit.enabled:false", "management.health.diskspace.enabled:false"); @@ -257,8 +251,7 @@ public class HealthIndicatorAutoConfigurationTests { public void solrHeathIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(SolrAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.diskspace.enabled:false"); this.context.refresh(); @@ -273,8 +266,7 @@ public class HealthIndicatorAutoConfigurationTests { public void notSolrHeathIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(SolrAutoConfiguration.class, - ManagementServerProperties.class, - HealthIndicatorAutoConfiguration.class); + ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "management.health.solr.enabled:false", "management.health.diskspace.enabled:false"); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata.java index ac4ff2f058..878b40ce8f 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata.java @@ -80,19 +80,20 @@ public class ConfigurationMetadata { Matcher matcher = CAMEL_CASE_PATTERN.matcher(name); StringBuffer result = new StringBuffer(); while (matcher.find()) { - String first = matcher.group(1); - String second = matcher.group(2); - String target; - if (first.equals("_")) { // not a word for the binder - target = first + second; - } else { - target = first + "-" + second; - } - matcher.appendReplacement(result,target); + matcher.appendReplacement(result, getDashed(matcher)); } matcher.appendTail(result); - String value = result.toString(); - return value.toLowerCase(); + return result.toString().toLowerCase(); + } + + private static String getDashed(Matcher matcher) { + String first = matcher.group(1); + String second = matcher.group(2); + if (first.equals("_")) { + // not a word for the binder + return first + second; + } + return first + "-" + second; } } diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadataTests.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadataTests.java index b99828dfd1..e383035037 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadataTests.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadataTests.java @@ -30,42 +30,46 @@ public class ConfigurationMetadataTests { @Test public void toDashedCaseCamelCase() { - assertThat(ConfigurationMetadata.toDashedCase("simpleCamelCase"), is("simple-camel-case")); + assertThat(toDashedCase("simpleCamelCase"), is("simple-camel-case")); } @Test public void toDashedCaseWordsUnderScore() { - assertThat(ConfigurationMetadata.toDashedCase("Word_With_underscore"), is("word_with_underscore")); + assertThat(toDashedCase("Word_With_underscore"), is("word_with_underscore")); } @Test public void toDashedCaseWordsSeveralUnderScores() { - assertThat(ConfigurationMetadata.toDashedCase("Word___With__underscore"), is("word___with__underscore")); + assertThat(toDashedCase("Word___With__underscore"), is("word___with__underscore")); } @Test public void toDashedCaseLowerCaseUnderscore() { - assertThat(ConfigurationMetadata.toDashedCase("lower_underscore"), is("lower_underscore")); + assertThat(toDashedCase("lower_underscore"), is("lower_underscore")); } @Test public void toDashedCaseUpperUnderscore() { - assertThat(ConfigurationMetadata.toDashedCase("UPPER_UNDERSCORE"), is("upper_underscore")); + assertThat(toDashedCase("UPPER_UNDERSCORE"), is("upper_underscore")); } @Test public void toDashedCaseMultipleUnderscores() { - assertThat(ConfigurationMetadata.toDashedCase("super___crazy"), is("super___crazy")); + assertThat(toDashedCase("super___crazy"), is("super___crazy")); } @Test public void toDashedCaseUppercase() { - assertThat(ConfigurationMetadata.toDashedCase("UPPERCASE"), is("uppercase")); + assertThat(toDashedCase("UPPERCASE"), is("uppercase")); } @Test public void toDashedCaseLowercase() { - assertThat(ConfigurationMetadata.toDashedCase("lowercase"), is("lowercase")); + assertThat(toDashedCase("lowercase"), is("lowercase")); + } + + private String toDashedCase(String name) { + return ConfigurationMetadata.toDashedCase(name); } }