diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfiguration.java index 4f5d81c9af..a47728f777 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfiguration.java @@ -16,12 +16,15 @@ package org.springframework.boot.actuate.autoconfigure; +import javax.management.MBeanServer; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -35,7 +38,7 @@ import org.springframework.util.StringUtils; */ @Configuration @ConditionalOnExpression("${endpoints.jmx.enabled:true} && ${spring.jmx.enabled:true}") -@AutoConfigureAfter({ EndpointAutoConfiguration.class }) +@AutoConfigureAfter({ EndpointAutoConfiguration.class, JmxAutoConfiguration.class }) @EnableConfigurationProperties(EndpointMBeanExportProperties.class) public class EndpointMBeanExportAutoConfiguration { @@ -43,13 +46,14 @@ public class EndpointMBeanExportAutoConfiguration { EndpointMBeanExportProperties properties = new EndpointMBeanExportProperties(); @Bean - public EndpointMBeanExporter endpointMBeanExporter() { + public EndpointMBeanExporter endpointMBeanExporter(MBeanServer server) { EndpointMBeanExporter mbeanExporter = new EndpointMBeanExporter(); String domain = this.properties.getDomain(); if (StringUtils.hasText(domain)) { mbeanExporter.setDomain(domain); } + mbeanExporter.setServer(server); mbeanExporter.setEnsureUniqueRuntimeObjectNames(this.properties.isUniqueNames()); mbeanExporter.setObjectNameStaticProperties(this.properties.getStaticNames()); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java index 2d6bb00f0f..29f1ed6fa9 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java @@ -26,6 +26,7 @@ import org.junit.After; import org.junit.Test; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter; +import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; @@ -56,7 +57,8 @@ public class EndpointMBeanExportAutoConfigurationTests { @Test public void testEndpointMBeanExporterIsInstalled() { this.context = new AnnotationConfigApplicationContext(); - this.context.register(TestConfiguration.class, EndpointAutoConfiguration.class, + this.context.register(TestConfiguration.class, JmxAutoConfiguration.class, + EndpointAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class); this.context.refresh(); assertNotNull(this.context.getBean(EndpointMBeanExporter.class)); @@ -68,7 +70,8 @@ public class EndpointMBeanExportAutoConfigurationTests { environment.setProperty("endpoints.jmx.enabled", "false"); this.context = new AnnotationConfigApplicationContext(); this.context.setEnvironment(environment); - this.context.register(EndpointAutoConfiguration.class, + this.context.register(JmxAutoConfiguration.class, + EndpointAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class); this.context.refresh(); this.context.getBean(EndpointMBeanExporter.class); @@ -84,7 +87,8 @@ public class EndpointMBeanExportAutoConfigurationTests { environment.setProperty("endpoints.jmx.static_names", "key1=value1, key2=value2"); this.context = new AnnotationConfigApplicationContext(); this.context.setEnvironment(environment); - this.context.register(EndpointAutoConfiguration.class, + this.context.register(JmxAutoConfiguration.class, + EndpointAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class); this.context.refresh(); this.context.getBean(EndpointMBeanExporter.class); @@ -101,11 +105,12 @@ public class EndpointMBeanExportAutoConfigurationTests { public void testEndpointMBeanExporterInParentChild() throws IntrospectionException, InstanceNotFoundException, MalformedObjectNameException, ReflectionException { this.context = new AnnotationConfigApplicationContext(); - this.context.register(EndpointAutoConfiguration.class, + this.context.register(JmxAutoConfiguration.class, + EndpointAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class); AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); - parent.register(EndpointAutoConfiguration.class, + parent.register(JmxAutoConfiguration.class, EndpointAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class); this.context.setParent(parent); diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml index 16d865e228..fa51c3640a 100644 --- a/spring-boot-autoconfigure/pom.xml +++ b/spring-boot-autoconfigure/pom.xml @@ -136,6 +136,11 @@ spring-integration-core true + + org.springframework.integration + spring-integration-jmx + true + org.springframework spring-jms diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java index f4ed848585..154f313dbd 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java @@ -16,19 +16,27 @@ package org.springframework.boot.autoconfigure.integration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport; +import org.springframework.integration.jmx.config.IntegrationMBeanExportConfiguration; /** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration * Auto-configuration} for Spring Integration. * * @author Artem Bilan + * @author Dave Syer * @since 1.1 */ @Configuration @ConditionalOnClass(EnableIntegration.class) +@AutoConfigureAfter(JmxAutoConfiguration.class) public class IntegrationAutoConfiguration { @Configuration @@ -36,4 +44,12 @@ public class IntegrationAutoConfiguration { protected static class IntegrationConfiguration { } + @Configuration + @ConditionalOnClass(EnableIntegrationMBeanExport.class) + @ConditionalOnMissingBean(IntegrationMBeanExportConfiguration.class) + @ConditionalOnExpression("${spring.jmx.enabled:true}") + @EnableIntegrationMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}") + protected static class IntegrationJmxConfiguration { + } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java index a3d01ed95e..1b53b3baaa 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java @@ -16,13 +16,17 @@ package org.springframework.boot.autoconfigure.jmx; +import javax.management.MBeanServer; + import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableMBeanExport; import org.springframework.jmx.export.MBeanExporter; +import org.springframework.jmx.support.MBeanServerFactoryBean; /** * {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's @@ -34,14 +38,21 @@ import org.springframework.jmx.export.MBeanExporter; */ @Configuration @ConditionalOnClass({ MBeanExporter.class }) -@ConditionalOnMissingBean({ MBeanExporter.class }) @ConditionalOnExpression("${spring.jmx.enabled:true}") public class JmxAutoConfiguration { @Configuration - @EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:}") + @ConditionalOnMissingBean({ MBeanExporter.class }) + @EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}") public static class MBeanExport { + } + @Bean + @ConditionalOnMissingBean(MBeanServer.class) + public MBeanServerFactoryBean mbeanServer() { + MBeanServerFactoryBean factory = new MBeanServerFactoryBean(); + factory.setLocateExistingServerIfPossible(true); + return factory; } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java index ff3dc4d87e..d3774b7344 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.integration; import org.junit.Test; +import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.integration.support.channel.HeaderChannelRegistry; @@ -32,7 +33,8 @@ public class IntegrationAutoConfigurationTests { @Test public void integrationIsAvailable() { - this.context.register(IntegrationAutoConfiguration.class); + this.context.register(JmxAutoConfiguration.class, + IntegrationAutoConfiguration.class); this.context.refresh(); assertNotNull(this.context.getBean(HeaderChannelRegistry.class)); this.context.close(); diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 3ebc52de28..a57771246b 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -1688,6 +1688,17 @@ infrastructure to receive messages asynchronously. Spring AMQP provides a simila feature set for the ``Advanced Message Queuing Protocol'' and Boot also provides auto-configuration options for `RabbitTemplate` and RabbitMQ. +[[boot-features-messaging]] +== Spring Integration + +Spring Integration provides abstractions over messaging and also other +transports such as HTTP, TCP etc. If Spring Integration is available +on your classpath it will be initialized through the `@EnableIntegration` +annotation. Message processing statistics will be published over JMX if +``spring-integration-jmx'' is also on the classpath. +See the {sc-spring-boot-autoconfigure}/integration/IntegrationAutoConfiguration.{sc-ext}[`IntegrationAutoConfiguration`] +class for more details. + [[boot-features-jms]] == JMS @@ -1792,6 +1803,17 @@ into your own beans: } ---- +[[boot-features-jmx]] +== Monitoring and management over JMX + +Java Management Extensions (JMX) provide a standard mechanism to +monitor and manage applications. By default Spring Boot will create an +`MBeanServer` with bean id "mbeanServer" and expose any of your beans +that are annotated with Spring JMX annotations (`@ManagedResource`, +`@ManagedAttribute`, `@ManagedOperation`). + +See the {sc-spring-boot-autoconfigure}/jmx/JmxAutoConfiguration.{sc-ext}[`JmxAutoConfiguration`] +class for more details. [[boot-features-testing]] == Testing diff --git a/spring-boot-samples/spring-boot-sample-integration/pom.xml b/spring-boot-samples/spring-boot-sample-integration/pom.xml index e4ead4891b..454e9571ed 100644 --- a/spring-boot-samples/spring-boot-sample-integration/pom.xml +++ b/spring-boot-samples/spring-boot-sample-integration/pom.xml @@ -23,6 +23,10 @@ org.springframework.boot spring-boot-starter-integration + + org.springframework.integration + spring-integration-jmx + org.springframework.boot spring-boot-starter-test diff --git a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties index 2ec8b7cad2..1fd64e4d13 100644 --- a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties +++ b/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties @@ -1,2 +1,3 @@ logging.file: /tmp/logs/app.log -service.greeting: Hello \ No newline at end of file +service.greeting: Hello +debug: true \ No newline at end of file