From 8ce7da9bb07c52658b743ff76cfa4f49afc789a1 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 7 Feb 2025 12:23:40 +0000 Subject: [PATCH] Avoid duplicate customization of management web server factory Previously, customization was performed in two places: 1. By customizers defined in the reactive and servlet web servlet factory auto-configuration - ServletWebServerFactoryAutoConfiguration - ReactiveWebServerFactoryAutoConfiguration 2. By a ManagementWebServerFactoryCustomizer that delegates to customizers of certain types found in the application context hierarchy. This led to some double customization as the customizers registered by the auto-configuration classes were also found and called by the ManagementWebServerFactoryCustomizer. Additionally, the ManagementWebServerFactoryCustomizer would find customizers from the parent context registered by EmbeddedWebServerFactoryCustomizerAutoConfiguration. This commit reworks the customization of the management web server factory to remove the double customization. ManagementWebServerFactoryCustomizer no longer delegates to customizers that it finds in the context hierarchy. This prevents the customizers defined in the reactive and servlet web server factory auto-configuration classes from being called twice. Additionally, EmbeddedWebServerFactoryCustomizerAutoConfiguration is now registered in the child context so that its customizers continue to be called when preparing the management context web server factory. Closes gh-44151 --- ...veManagementChildContextConfiguration.java | 29 +++---------------- ...iveManagementContextAutoConfiguration.java | 6 ++-- .../ManagementWebServerFactoryCustomizer.java | 20 +++++++++++-- ...etManagementChildContextConfiguration.java | 13 +-------- ...letManagementContextAutoConfiguration.java | 4 ++- 5 files changed, 29 insertions(+), 43 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java index d28ec5d415..971ec28163 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,15 +26,7 @@ import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServe import org.springframework.boot.actuate.autoconfigure.web.server.ManagementWebServerFactoryCustomizer; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; -import org.springframework.boot.autoconfigure.web.embedded.JettyVirtualThreadsWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.embedded.JettyWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryCustomizer; -import org.springframework.boot.autoconfigure.web.reactive.TomcatReactiveWebServerFactoryCustomizer; -import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory; +import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.http.server.reactive.ContextPathCompositeHandler; @@ -58,9 +50,9 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder; public class ReactiveManagementChildContextConfiguration { @Bean - public ReactiveManagementWebServerFactoryCustomizer reactiveManagementWebServerFactoryCustomizer( + public ManagementWebServerFactoryCustomizer reactiveManagementWebServerFactoryCustomizer( ListableBeanFactory beanFactory) { - return new ReactiveManagementWebServerFactoryCustomizer(beanFactory); + return new ManagementWebServerFactoryCustomizer<>(beanFactory); } @Bean @@ -73,17 +65,4 @@ public class ReactiveManagementChildContextConfiguration { return httpHandler; } - static class ReactiveManagementWebServerFactoryCustomizer - extends ManagementWebServerFactoryCustomizer { - - ReactiveManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) { - super(beanFactory, ReactiveWebServerFactoryCustomizer.class, TomcatWebServerFactoryCustomizer.class, - TomcatReactiveWebServerFactoryCustomizer.class, - TomcatVirtualThreadsWebServerFactoryCustomizer.class, JettyWebServerFactoryCustomizer.class, - JettyVirtualThreadsWebServerFactoryCustomizer.class, UndertowWebServerFactoryCustomizer.class, - NettyWebServerFactoryCustomizer.class); - } - - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java index 25004ecebc..5afb49200b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementContextAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; @@ -44,7 +45,8 @@ public class ReactiveManagementContextAutoConfiguration { @Bean public static ManagementContextFactory reactiveWebChildContextFactory() { return new ManagementContextFactory(WebApplicationType.REACTIVE, ReactiveWebServerFactory.class, - ReactiveWebServerFactoryAutoConfiguration.class); + ReactiveWebServerFactoryAutoConfiguration.class, + EmbeddedWebServerFactoryCustomizerAutoConfiguration.class); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java index aa13066f14..265eaf6d5f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ import org.springframework.core.Ordered; * @author Andy Wilkinson * @since 2.0.0 */ -public abstract class ManagementWebServerFactoryCustomizer +public class ManagementWebServerFactoryCustomizer implements WebServerFactoryCustomizer, Ordered { private final ListableBeanFactory beanFactory; @@ -48,12 +48,24 @@ public abstract class ManagementWebServerFactoryCustomizer>... customizerClasses) { this.beanFactory = beanFactory; this.customizerClasses = customizerClasses; } + /** + * Creates a new customizer that will retrieve beans using the given + * {@code beanFactory}. + * @param beanFactory the bean factory to use + * @since 3.5.0 + */ + public ManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) { + this.beanFactory = beanFactory; + this.customizerClasses = null; + } + @Override public int getOrder() { return 0; @@ -65,7 +77,9 @@ public abstract class ManagementWebServerFactoryCustomizer { ServletManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) { - super(beanFactory, ServletWebServerFactoryCustomizer.class, TomcatServletWebServerFactoryCustomizer.class, - TomcatWebServerFactoryCustomizer.class, TomcatVirtualThreadsWebServerFactoryCustomizer.class, - JettyWebServerFactoryCustomizer.class, JettyVirtualThreadsWebServerFactoryCustomizer.class, - UndertowServletWebServerFactoryCustomizer.class, UndertowWebServerFactoryCustomizer.class); + super(beanFactory); } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java index 3a46d076f2..854ecc26b7 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProp import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; +import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.web.servlet.filter.ApplicationContextHeaderFilter; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; @@ -49,7 +50,8 @@ public class ServletManagementContextAutoConfiguration { @Bean public static ManagementContextFactory servletWebChildContextFactory() { return new ManagementContextFactory(WebApplicationType.SERVLET, ServletWebServerFactory.class, - ServletWebServerFactoryAutoConfiguration.class); + ServletWebServerFactoryAutoConfiguration.class, + EmbeddedWebServerFactoryCustomizerAutoConfiguration.class); } @Bean