Commit 09200361 authored by Dave Syer's avatar Dave Syer

Align expectations of various JMX configurations

They all want to create an MBeanServer and when that happens
user sees no MBeans, or sometimes just one set (Spring Core,
Spring Integration or Spring Boot). To harmonise them we
create a @Bean of type MBeanServer and link to it in the
other autoconfigs

Fixes gh-1046
parent 6f98c63a
......@@ -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());
......
......@@ -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);
......
......@@ -136,6 +136,11 @@
<artifactId>spring-integration-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
......
......@@ -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 {
}
}
......@@ -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;
}
}
......@@ -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();
......
......@@ -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
......
......@@ -23,6 +23,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
......
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment