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
This commit is contained in:
Dave Syer 2014-06-06 16:10:56 +01:00
parent 6f98c63ac0
commit 09200361de
9 changed files with 81 additions and 11 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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>

View File

@ -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 {
}
}

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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

View File

@ -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>

View File

@ -1,2 +1,3 @@
logging.file: /tmp/logs/app.log
service.greeting: Hello
service.greeting: Hello
debug: true