diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java index 1687b696c4..66b72769f7 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java @@ -30,11 +30,14 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.mvc.ManagementServletContext; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -55,6 +58,7 @@ import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfigurat import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -104,6 +108,8 @@ public class EndpointWebMvcAutoConfiguration private static final Log logger = LogFactory .getLog(EndpointWebMvcAutoConfiguration.class); + private static final ConfigurableListableBeanFactory BeanDefinitionRegistry = null; + private ApplicationContext applicationContext; private BeanFactory beanFactory; @@ -164,7 +170,7 @@ public class EndpointWebMvcAutoConfiguration } private void createChildManagementContext() { - final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext(); + AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext(); childContext.setParent(this.applicationContext); childContext.setNamespace("management"); childContext.setId(this.applicationContext.getId() + ":management"); @@ -172,12 +178,30 @@ public class EndpointWebMvcAutoConfiguration PropertyPlaceholderAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, DispatcherServletAutoConfiguration.class); + registerEmbeddedServletContainerFactory(childContext); CloseEventPropagationListener.addIfPossible(this.applicationContext, childContext); childContext.refresh(); managementContextResolver().setApplicationContext(childContext); } + private void registerEmbeddedServletContainerFactory( + AnnotationConfigEmbeddedWebApplicationContext childContext) { + try { + EmbeddedServletContainerFactory servletContainerFactory = this.applicationContext + .getBean(EmbeddedServletContainerFactory.class); + ConfigurableListableBeanFactory beanFactory = childContext.getBeanFactory(); + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + registry.registerBeanDefinition("embeddedServletContainerFactory", + new RootBeanDefinition(servletContainerFactory.getClass())); + } + } + catch (NoSuchBeanDefinitionException ex) { + // Ignore and assume auto-configuration + } + } + /** * Add an alias for 'local.management.port' that actually resolves using * 'local.server.port'. diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java index 3f7bfb2146..cf2b94b32b 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java @@ -58,7 +58,9 @@ import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebAppl import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerException; +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.ApplicationContext; @@ -85,6 +87,7 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -177,6 +180,35 @@ public class EndpointWebMvcAutoConfigurationTests { assertAllClosed(); } + @Test + public void onDifferentPortWithSpecificContainer() throws Exception { + this.applicationContext.register(SpecificContainerConfig.class, RootConfig.class, + DifferentPortConfig.class, EndpointConfig.class, BaseConfiguration.class, + EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class); + this.applicationContext.refresh(); + assertContent("/controller", ports.get().server, "controlleroutput"); + assertContent("/endpoint", ports.get().server, null); + assertContent("/controller", ports.get().management, null); + assertContent("/endpoint", ports.get().management, "endpointoutput"); + assertContent("/error", ports.get().management, startsWith("{")); + ApplicationContext managementContext = this.applicationContext + .getBean(ManagementContextResolver.class).getApplicationContext(); + List interceptors = (List) ReflectionTestUtils.getField( + managementContext.getBean(EndpointHandlerMapping.class), "interceptors"); + assertEquals(1, interceptors.size()); + EmbeddedServletContainerFactory parentContainerFactory = this.applicationContext + .getBean(EmbeddedServletContainerFactory.class); + EmbeddedServletContainerFactory managementContainerFactory = managementContext + .getBean(EmbeddedServletContainerFactory.class); + assertThat(parentContainerFactory, + instanceOf(SpecificEmbeddedServletContainerFactory.class)); + assertThat(managementContainerFactory, + instanceOf(SpecificEmbeddedServletContainerFactory.class)); + assertThat(managementContainerFactory, not(sameInstance(parentContainerFactory))); + this.applicationContext.close(); + assertAllClosed(); + } + @Test public void onDifferentPortAndContext() throws Exception { this.applicationContext.register(RootConfig.class, EndpointConfig.class, @@ -611,6 +643,16 @@ public class EndpointWebMvcAutoConfigurationTests { } + @Configuration + public static class SpecificContainerConfig { + + @Bean + public SpecificEmbeddedServletContainerFactory embeddedServletContainerFactory() { + return new SpecificEmbeddedServletContainerFactory(); + } + + } + @Configuration @Import(ServerPortConfig.class) public static class DifferentPortConfig { @@ -638,6 +680,7 @@ public class EndpointWebMvcAutoConfigurationTests { } protected static class TestInterceptor extends HandlerInterceptorAdapter { + private int count = 0; @Override @@ -650,6 +693,7 @@ public class EndpointWebMvcAutoConfigurationTests { public int getCount() { return this.count; } + } } @@ -730,4 +774,9 @@ public class EndpointWebMvcAutoConfigurationTests { } + private static class SpecificEmbeddedServletContainerFactory + extends TomcatEmbeddedServletContainerFactory { + + } + }