/* * 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.autoconfigure.admin; import java.lang.management.ManagementFactory; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectInstance; import javax.management.ObjectName; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.WebApplicationType; import org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar; import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; /** * Tests for {@link SpringApplicationAdminJmxAutoConfiguration}. * * @author Stephane Nicoll * @author Andy Wilkinson */ public class SpringApplicationAdminJmxAutoConfigurationTests { private static final String ENABLE_ADMIN_PROP = "spring.application.admin.enabled=true"; private static final String JMX_NAME_PROPERTY = "spring.application.admin.jmx-name"; private static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Admin,name=SpringApplication"; @Rule public final ExpectedException thrown = ExpectedException.none(); private ConfigurableApplicationContext context; private MBeanServer mBeanServer; @Before public void setup() throws MalformedObjectNameException { this.mBeanServer = ManagementFactory.getPlatformMBeanServer(); } @After public void tearDown() { if (this.context != null) { this.context.close(); } } @Test public void notRegisteredByDefault() throws MalformedObjectNameException, InstanceNotFoundException { load(); this.thrown.expect(InstanceNotFoundException.class); this.mBeanServer.getObjectInstance(createDefaultObjectName()); } @Test public void registeredWithProperty() throws Exception { load(ENABLE_ADMIN_PROP); ObjectName objectName = createDefaultObjectName(); ObjectInstance objectInstance = this.mBeanServer.getObjectInstance(objectName); assertThat(objectInstance).as("Lifecycle bean should have been registered") .isNotNull(); } @Test public void registerWithCustomJmxName() throws InstanceNotFoundException { String customJmxName = "org.acme:name=FooBar"; System.setProperty(JMX_NAME_PROPERTY, customJmxName); try { load(ENABLE_ADMIN_PROP); try { this.mBeanServer.getObjectInstance(createObjectName(customJmxName)); } catch (InstanceNotFoundException ex) { fail("Admin MBean should have been exposed with custom name"); } this.thrown.expect(InstanceNotFoundException.class); // Should not be exposed this.mBeanServer.getObjectInstance(createDefaultObjectName()); } finally { System.clearProperty(JMX_NAME_PROPERTY); } } @Test public void registerWithSimpleWebApp() throws Exception { this.context = new SpringApplicationBuilder() .sources(ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class, JmxAutoConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class) .run("--" + ENABLE_ADMIN_PROP, "--server.port=0"); assertThat(this.context).isInstanceOf(ServletWebServerApplicationContext.class); assertThat(this.mBeanServer.getAttribute(createDefaultObjectName(), "EmbeddedWebApplication")).isEqualTo(Boolean.TRUE); int expected = ((ServletWebServerApplicationContext) this.context) .getWebServer().getPort(); String actual = getProperty(createDefaultObjectName(), "local.server.port"); assertThat(actual).isEqualTo(String.valueOf(expected)); } @Test public void onlyRegisteredOnceWhenThereIsAChildContext() throws Exception { SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder() .web(WebApplicationType.NONE).sources(JmxAutoConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class); SpringApplicationBuilder childBuilder = parentBuilder .child(JmxAutoConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class) .web(WebApplicationType.NONE); ConfigurableApplicationContext parent = null; ConfigurableApplicationContext child = null; try { parent = parentBuilder.run("--" + ENABLE_ADMIN_PROP); child = childBuilder.run("--" + ENABLE_ADMIN_PROP); BeanFactoryUtils.beanOfType(parent.getBeanFactory(), SpringApplicationAdminMXBeanRegistrar.class); this.thrown.expect(NoSuchBeanDefinitionException.class); BeanFactoryUtils.beanOfType(child.getBeanFactory(), SpringApplicationAdminMXBeanRegistrar.class); } finally { if (parent != null) { parent.close(); } if (child != null) { child.close(); } } } private ObjectName createDefaultObjectName() { return createObjectName(DEFAULT_JMX_NAME); } private ObjectName createObjectName(String jmxName) { try { return new ObjectName(jmxName); } catch (MalformedObjectNameException ex) { throw new IllegalStateException("Invalid jmx name " + jmxName, ex); } } private String getProperty(ObjectName objectName, String key) throws Exception { return (String) this.mBeanServer.invoke(objectName, "getProperty", new Object[] { key }, new String[] { String.class.getName() }); } private void load(String... environment) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(applicationContext, environment); applicationContext.register(JmxAutoConfiguration.class, SpringApplicationAdminJmxAutoConfiguration.class); applicationContext.refresh(); this.context = applicationContext; } }