Skip to content

Commit b603cd5

Browse files
committed
Disable Tomcat's MBean Registry by default
Closes gh-16498
1 parent 080a2f5 commit b603cd5

File tree

9 files changed

+119
-16
lines changed

9 files changed

+119
-16
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer;
2828
import org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer;
2929
import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryCustomizer;
30+
import org.springframework.boot.autoconfigure.web.reactive.TomcatReactiveWebServerFactoryCustomizer;
3031
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
3132
import org.springframework.context.ApplicationContext;
3233
import org.springframework.context.annotation.Bean;
@@ -65,6 +66,7 @@ class ReactiveManagementWebServerFactoryCustomizer extends
6566
ReactiveManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) {
6667
super(beanFactory, ReactiveWebServerFactoryCustomizer.class,
6768
TomcatWebServerFactoryCustomizer.class,
69+
TomcatReactiveWebServerFactoryCustomizer.class,
6870
JettyWebServerFactoryCustomizer.class,
6971
UndertowWebServerFactoryCustomizer.class,
7072
NettyWebServerFactoryCustomizer.class);

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfigurationTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
package org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat;
1818

1919
import java.util.Collections;
20+
import java.util.concurrent.atomic.AtomicInteger;
2021

2122
import io.micrometer.core.instrument.MeterRegistry;
2223
import io.micrometer.core.instrument.binder.tomcat.TomcatMetrics;
2324
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
25+
import org.apache.tomcat.util.modeler.Registry;
2426
import org.junit.jupiter.api.Test;
2527

2628
import org.springframework.boot.SpringApplication;
@@ -33,11 +35,13 @@
3335
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
3436
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
3537
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
38+
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
3639
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
3740
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
3841
import org.springframework.context.annotation.Bean;
3942
import org.springframework.context.annotation.Configuration;
4043
import org.springframework.http.server.reactive.HttpHandler;
44+
import org.springframework.test.util.ReflectionTestUtils;
4145

4246
import static org.assertj.core.api.Assertions.assertThat;
4347
import static org.mockito.Mockito.mock;
@@ -51,13 +55,15 @@ public class TomcatMetricsAutoConfigurationTests {
5155

5256
@Test
5357
public void autoConfiguresTomcatMetricsWithEmbeddedServletTomcat() {
58+
resetTomcatState();
5459
new WebApplicationContextRunner(
5560
AnnotationConfigServletWebServerApplicationContext::new)
5661
.withConfiguration(AutoConfigurations.of(
5762
TomcatMetricsAutoConfiguration.class,
5863
ServletWebServerFactoryAutoConfiguration.class))
5964
.withUserConfiguration(ServletWebServerConfiguration.class,
6065
MeterRegistryConfiguration.class)
66+
.withPropertyValues("server.tomcat.mbeanregistry.enabled=true")
6167
.run((context) -> {
6268
context.publishEvent(
6369
new ApplicationStartedEvent(new SpringApplication(),
@@ -75,13 +81,15 @@ public void autoConfiguresTomcatMetricsWithEmbeddedServletTomcat() {
7581

7682
@Test
7783
public void autoConfiguresTomcatMetricsWithEmbeddedReactiveTomcat() {
84+
resetTomcatState();
7885
new ReactiveWebApplicationContextRunner(
7986
AnnotationConfigReactiveWebServerApplicationContext::new)
8087
.withConfiguration(AutoConfigurations.of(
8188
TomcatMetricsAutoConfiguration.class,
8289
ReactiveWebServerFactoryAutoConfiguration.class))
8390
.withUserConfiguration(ReactiveWebServerConfiguration.class,
8491
MeterRegistryConfiguration.class)
92+
.withPropertyValues("server.tomcat.mbeanregistry.enabled=true")
8593
.run((context) -> {
8694
context.publishEvent(
8795
new ApplicationStartedEvent(new SpringApplication(),
@@ -130,6 +138,13 @@ public void allowsCustomTomcatMetricsToBeUsed() {
130138
.hasBean("customTomcatMetrics"));
131139
}
132140

141+
private void resetTomcatState() {
142+
ReflectionTestUtils.setField(Registry.class, "registry", null);
143+
AtomicInteger containerCounter = (AtomicInteger) ReflectionTestUtils
144+
.getField(TomcatWebServer.class, "containerCounter");
145+
containerCounter.set(-1);
146+
}
147+
133148
@Configuration(proxyBeanMethods = false)
134149
static class MeterRegistryConfiguration {
135150

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/BackgroundPreinitializer.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import javax.validation.Configuration;
2424
import javax.validation.Validation;
2525

26-
import org.apache.catalina.mbeans.MBeanFactory;
27-
2826
import org.springframework.boot.context.event.ApplicationFailedEvent;
2927
import org.springframework.boot.context.event.ApplicationReadyEvent;
3028
import org.springframework.boot.context.event.ApplicationStartingEvent;
@@ -99,7 +97,6 @@ public void run() {
9997
runSafely(new ConversionServiceInitializer());
10098
runSafely(new ValidationInitializer());
10199
runSafely(new MessageConverterInitializer());
102-
runSafely(new MBeanFactoryInitializer());
103100
runSafely(new JacksonInitializer());
104101
runSafely(new CharsetInitializer());
105102
preinitializationComplete.countDown();
@@ -137,18 +134,6 @@ public void run() {
137134

138135
}
139136

140-
/**
141-
* Early initializer to load Tomcat MBean XML.
142-
*/
143-
private static class MBeanFactoryInitializer implements Runnable {
144-
145-
@Override
146-
public void run() {
147-
new MBeanFactory();
148-
}
149-
150-
}
151-
152137
/**
153138
* Early initializer for javax.validation.
154139
*/

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,11 @@ public static class Tomcat {
400400
*/
401401
private final Resource resource = new Resource();
402402

403+
/**
404+
* Modeler MBean Registry configuration.
405+
*/
406+
private final Mbeanregistry mbeanregistry = new Mbeanregistry();
407+
403408
public int getMaxThreads() {
404409
return this.maxThreads;
405410
}
@@ -552,6 +557,10 @@ public Resource getResource() {
552557
return this.resource;
553558
}
554559

560+
public Mbeanregistry getMbeanregistry() {
561+
return this.mbeanregistry;
562+
}
563+
555564
/**
556565
* Tomcat access log properties.
557566
*/
@@ -821,6 +830,23 @@ public void setCacheTtl(Duration cacheTtl) {
821830

822831
}
823832

833+
public static class Mbeanregistry {
834+
835+
/**
836+
* Whether Tomcat's MBean Registry should be enabled.
837+
*/
838+
private boolean enabled;
839+
840+
public boolean isEnabled() {
841+
return this.enabled;
842+
}
843+
844+
public void setEnabled(boolean enabled) {
845+
this.enabled = enabled;
846+
}
847+
848+
}
849+
824850
}
825851

826852
/**

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.beans.factory.ObjectProvider;
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
27+
import org.springframework.boot.autoconfigure.web.ServerProperties;
2728
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
2829
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
2930
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
@@ -98,6 +99,12 @@ public TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory(
9899
return factory;
99100
}
100101

102+
@Bean
103+
public TomcatReactiveWebServerFactoryCustomizer tomcatReactiveWebServerFactoryCustomizer(
104+
ServerProperties serverProperties) {
105+
return new TomcatReactiveWebServerFactoryCustomizer(serverProperties);
106+
}
107+
101108
}
102109

103110
@Configuration(proxyBeanMethods = false)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.web.reactive;
18+
19+
import org.apache.tomcat.util.modeler.Registry;
20+
21+
import org.springframework.boot.autoconfigure.web.ServerProperties;
22+
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
23+
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
24+
25+
/**
26+
* {@link WebServerFactoryCustomizer} to apply {@link ServerProperties} to Tomcat reactive
27+
* web servers.
28+
*
29+
* @author Andy Wilkinson
30+
* @since 2.2.0
31+
*/
32+
public class TomcatReactiveWebServerFactoryCustomizer
33+
implements WebServerFactoryCustomizer<TomcatReactiveWebServerFactory> {
34+
35+
private final ServerProperties serverProperties;
36+
37+
public TomcatReactiveWebServerFactoryCustomizer(ServerProperties serverProperties) {
38+
this.serverProperties = serverProperties;
39+
}
40+
41+
@Override
42+
public void customize(TomcatReactiveWebServerFactory factory) {
43+
if (!this.serverProperties.getTomcat().getMbeanregistry().isEnabled()) {
44+
Registry.disableRegistry();
45+
}
46+
}
47+
48+
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.autoconfigure.web.servlet;
1818

19+
import org.apache.tomcat.util.modeler.Registry;
20+
1921
import org.springframework.boot.autoconfigure.web.ServerProperties;
2022
import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
2123
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@@ -60,6 +62,9 @@ public void customize(TomcatServletWebServerFactory factory) {
6062
customizeUseRelativeRedirects(factory,
6163
tomcatProperties.getUseRelativeRedirects());
6264
}
65+
if (!tomcatProperties.getMbeanregistry().isEnabled()) {
66+
Registry.disableRegistry();
67+
}
6368
}
6469

6570
private void customizeRedirectContextRoot(ConfigurableTomcatWebServerFactory factory,

spring-boot-project/spring-boot-docs/src/main/asciidoc/howto.adoc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,20 @@ include::{code-examples}/context/embedded/TomcatLegacyCookieProcessorExample.jav
10751075

10761076

10771077

1078+
[[howto-enable-tomcat-mbean-registry]]
1079+
=== Enable Tomcat's MBean Registry
1080+
Embedded Tomcat's MBean registry is disabled by default. This minimizes Tomcat's memory
1081+
footprint. If you want to use Tomcat's MBeans, for example so that they can be used to
1082+
expose metrics via Micrometer, you must use the `server.tomcat.mbeanregistry.enabled`
1083+
property to do so, as shown in the following example:
1084+
1085+
[source,properties,indent=0]
1086+
----
1087+
server.tomcat.mbeanregistry.enabled=true
1088+
----
1089+
1090+
1091+
10781092
[[howto-enable-multiple-listeners-in-undertow]]
10791093
=== Enable Multiple Listeners with Undertow
10801094
Add an `UndertowBuilderCustomizer` to the `UndertowServletWebServerFactory` and

spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1793,7 +1793,8 @@ Spring Boot registers the following core metrics when applicable:
17931793
* Logback metrics: record the number of events logged to Logback at each level
17941794
* Uptime metrics: report a gauge for uptime and a fixed gauge representing the
17951795
application's absolute start time
1796-
* Tomcat metrics
1796+
* Tomcat metrics (`server.tomcat.mbeanregistry.enabled` must be set to `true` for all
1797+
Tomcat metrics to be registered)
17971798
* https://docs.spring.io/spring-integration/docs/current/reference/html/system-management-chapter.html#micrometer-integration[Spring Integration] metrics
17981799

17991800

0 commit comments

Comments
 (0)