Skip to content

Commit 0920036

Browse files
author
Dave Syer
committed
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
1 parent 6f98c63 commit 0920036

File tree

9 files changed

+81
-11
lines changed

9 files changed

+81
-11
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfiguration.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure;
1818

19+
import javax.management.MBeanServer;
20+
1921
import org.springframework.beans.factory.annotation.Autowired;
2022
import org.springframework.boot.actuate.endpoint.Endpoint;
2123
import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter;
2224
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2325
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2426
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
27+
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
2528
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2629
import org.springframework.context.annotation.Bean;
2730
import org.springframework.context.annotation.Configuration;
@@ -35,21 +38,22 @@
3538
*/
3639
@Configuration
3740
@ConditionalOnExpression("${endpoints.jmx.enabled:true} && ${spring.jmx.enabled:true}")
38-
@AutoConfigureAfter({ EndpointAutoConfiguration.class })
41+
@AutoConfigureAfter({ EndpointAutoConfiguration.class, JmxAutoConfiguration.class })
3942
@EnableConfigurationProperties(EndpointMBeanExportProperties.class)
4043
public class EndpointMBeanExportAutoConfiguration {
4144

4245
@Autowired
4346
EndpointMBeanExportProperties properties = new EndpointMBeanExportProperties();
4447

4548
@Bean
46-
public EndpointMBeanExporter endpointMBeanExporter() {
49+
public EndpointMBeanExporter endpointMBeanExporter(MBeanServer server) {
4750
EndpointMBeanExporter mbeanExporter = new EndpointMBeanExporter();
4851

4952
String domain = this.properties.getDomain();
5053
if (StringUtils.hasText(domain)) {
5154
mbeanExporter.setDomain(domain);
5255
}
56+
mbeanExporter.setServer(server);
5357

5458
mbeanExporter.setEnsureUniqueRuntimeObjectNames(this.properties.isUniqueNames());
5559
mbeanExporter.setObjectNameStaticProperties(this.properties.getStaticNames());

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.junit.Test;
2727
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2828
import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter;
29+
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
2930
import org.springframework.context.ApplicationContext;
3031
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3132
import org.springframework.context.annotation.Configuration;
@@ -56,7 +57,8 @@ public void close() {
5657
@Test
5758
public void testEndpointMBeanExporterIsInstalled() {
5859
this.context = new AnnotationConfigApplicationContext();
59-
this.context.register(TestConfiguration.class, EndpointAutoConfiguration.class,
60+
this.context.register(TestConfiguration.class, JmxAutoConfiguration.class,
61+
EndpointAutoConfiguration.class,
6062
EndpointMBeanExportAutoConfiguration.class);
6163
this.context.refresh();
6264
assertNotNull(this.context.getBean(EndpointMBeanExporter.class));
@@ -68,7 +70,8 @@ public void testEndpointMBeanExporterIsNotInstalled() {
6870
environment.setProperty("endpoints.jmx.enabled", "false");
6971
this.context = new AnnotationConfigApplicationContext();
7072
this.context.setEnvironment(environment);
71-
this.context.register(EndpointAutoConfiguration.class,
73+
this.context.register(JmxAutoConfiguration.class,
74+
EndpointAutoConfiguration.class,
7275
EndpointMBeanExportAutoConfiguration.class);
7376
this.context.refresh();
7477
this.context.getBean(EndpointMBeanExporter.class);
@@ -84,7 +87,8 @@ public void testEndpointMBeanExporterWithProperties() throws IntrospectionExcept
8487
environment.setProperty("endpoints.jmx.static_names", "key1=value1, key2=value2");
8588
this.context = new AnnotationConfigApplicationContext();
8689
this.context.setEnvironment(environment);
87-
this.context.register(EndpointAutoConfiguration.class,
90+
this.context.register(JmxAutoConfiguration.class,
91+
EndpointAutoConfiguration.class,
8892
EndpointMBeanExportAutoConfiguration.class);
8993
this.context.refresh();
9094
this.context.getBean(EndpointMBeanExporter.class);
@@ -101,11 +105,12 @@ public void testEndpointMBeanExporterWithProperties() throws IntrospectionExcept
101105
public void testEndpointMBeanExporterInParentChild() throws IntrospectionException,
102106
InstanceNotFoundException, MalformedObjectNameException, ReflectionException {
103107
this.context = new AnnotationConfigApplicationContext();
104-
this.context.register(EndpointAutoConfiguration.class,
108+
this.context.register(JmxAutoConfiguration.class,
109+
EndpointAutoConfiguration.class,
105110
EndpointMBeanExportAutoConfiguration.class);
106111

107112
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
108-
parent.register(EndpointAutoConfiguration.class,
113+
parent.register(JmxAutoConfiguration.class, EndpointAutoConfiguration.class,
109114
EndpointMBeanExportAutoConfiguration.class);
110115
this.context.setParent(parent);
111116

spring-boot-autoconfigure/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@
136136
<artifactId>spring-integration-core</artifactId>
137137
<optional>true</optional>
138138
</dependency>
139+
<dependency>
140+
<groupId>org.springframework.integration</groupId>
141+
<artifactId>spring-integration-jmx</artifactId>
142+
<optional>true</optional>
143+
</dependency>
139144
<dependency>
140145
<groupId>org.springframework</groupId>
141146
<artifactId>spring-jms</artifactId>

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,40 @@
1616

1717
package org.springframework.boot.autoconfigure.integration;
1818

19+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
1920
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
23+
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
2024
import org.springframework.context.annotation.Configuration;
2125
import org.springframework.integration.config.EnableIntegration;
26+
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
27+
import org.springframework.integration.jmx.config.IntegrationMBeanExportConfiguration;
2228

2329
/**
2430
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
2531
* Auto-configuration} for Spring Integration.
2632
*
2733
* @author Artem Bilan
34+
* @author Dave Syer
2835
* @since 1.1
2936
*/
3037
@Configuration
3138
@ConditionalOnClass(EnableIntegration.class)
39+
@AutoConfigureAfter(JmxAutoConfiguration.class)
3240
public class IntegrationAutoConfiguration {
3341

3442
@Configuration
3543
@EnableIntegration
3644
protected static class IntegrationConfiguration {
3745
}
3846

47+
@Configuration
48+
@ConditionalOnClass(EnableIntegrationMBeanExport.class)
49+
@ConditionalOnMissingBean(IntegrationMBeanExportConfiguration.class)
50+
@ConditionalOnExpression("${spring.jmx.enabled:true}")
51+
@EnableIntegrationMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}")
52+
protected static class IntegrationJmxConfiguration {
53+
}
54+
3955
}

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
package org.springframework.boot.autoconfigure.jmx;
1818

19+
import javax.management.MBeanServer;
20+
1921
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2022
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2123
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
2224
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.context.annotation.Bean;
2326
import org.springframework.context.annotation.Configuration;
2427
import org.springframework.context.annotation.EnableMBeanExport;
2528
import org.springframework.jmx.export.MBeanExporter;
29+
import org.springframework.jmx.support.MBeanServerFactoryBean;
2630

2731
/**
2832
* {@link EnableAutoConfiguration Auto-configuration} to enable/disable Spring's
@@ -34,14 +38,21 @@
3438
*/
3539
@Configuration
3640
@ConditionalOnClass({ MBeanExporter.class })
37-
@ConditionalOnMissingBean({ MBeanExporter.class })
3841
@ConditionalOnExpression("${spring.jmx.enabled:true}")
3942
public class JmxAutoConfiguration {
4043

4144
@Configuration
42-
@EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:}")
45+
@ConditionalOnMissingBean({ MBeanExporter.class })
46+
@EnableMBeanExport(defaultDomain = "${spring.jmx.default_domain:}", server = "${spring.jmx.server:mbeanServer}")
4347
public static class MBeanExport {
48+
}
4449

50+
@Bean
51+
@ConditionalOnMissingBean(MBeanServer.class)
52+
public MBeanServerFactoryBean mbeanServer() {
53+
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
54+
factory.setLocateExistingServerIfPossible(true);
55+
return factory;
4556
}
4657

4758
}

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.autoconfigure.integration;
1818

1919
import org.junit.Test;
20+
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
2021
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2122
import org.springframework.integration.support.channel.HeaderChannelRegistry;
2223

@@ -32,7 +33,8 @@ public class IntegrationAutoConfigurationTests {
3233

3334
@Test
3435
public void integrationIsAvailable() {
35-
this.context.register(IntegrationAutoConfiguration.class);
36+
this.context.register(JmxAutoConfiguration.class,
37+
IntegrationAutoConfiguration.class);
3638
this.context.refresh();
3739
assertNotNull(this.context.getBean(HeaderChannelRegistry.class));
3840
this.context.close();

spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,17 @@ infrastructure to receive messages asynchronously. Spring AMQP provides a simila
16881688
feature set for the ``Advanced Message Queuing Protocol'' and Boot also provides
16891689
auto-configuration options for `RabbitTemplate` and RabbitMQ.
16901690

1691+
[[boot-features-messaging]]
1692+
== Spring Integration
1693+
1694+
Spring Integration provides abstractions over messaging and also other
1695+
transports such as HTTP, TCP etc. If Spring Integration is available
1696+
on your classpath it will be initialized through the `@EnableIntegration`
1697+
annotation. Message processing statistics will be published over JMX if
1698+
``spring-integration-jmx'' is also on the classpath.
1699+
See the {sc-spring-boot-autoconfigure}/integration/IntegrationAutoConfiguration.{sc-ext}[`IntegrationAutoConfiguration`]
1700+
class for more details.
1701+
16911702
[[boot-features-jms]]
16921703
== JMS
16931704

@@ -1792,6 +1803,17 @@ into your own beans:
17921803
}
17931804
----
17941805

1806+
[[boot-features-jmx]]
1807+
== Monitoring and management over JMX
1808+
1809+
Java Management Extensions (JMX) provide a standard mechanism to
1810+
monitor and manage applications. By default Spring Boot will create an
1811+
`MBeanServer` with bean id "mbeanServer" and expose any of your beans
1812+
that are annotated with Spring JMX annotations (`@ManagedResource`,
1813+
`@ManagedAttribute`, `@ManagedOperation`).
1814+
1815+
See the {sc-spring-boot-autoconfigure}/jmx/JmxAutoConfiguration.{sc-ext}[`JmxAutoConfiguration`]
1816+
class for more details.
17951817

17961818
[[boot-features-testing]]
17971819
== Testing

spring-boot-samples/spring-boot-sample-integration/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
<groupId>org.springframework.boot</groupId>
2424
<artifactId>spring-boot-starter-integration</artifactId>
2525
</dependency>
26+
<dependency>
27+
<groupId>org.springframework.integration</groupId>
28+
<artifactId>spring-integration-jmx</artifactId>
29+
</dependency>
2630
<dependency>
2731
<groupId>org.springframework.boot</groupId>
2832
<artifactId>spring-boot-starter-test</artifactId>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
logging.file: /tmp/logs/app.log
2-
service.greeting: Hello
2+
service.greeting: Hello
3+
debug: true

0 commit comments

Comments
 (0)