Skip to content

Commit 6c8f8c9

Browse files
committed
Better diagnotics when ESCF subclass breaks with custom management port
When a custom management.port is used, the child context is configured with an EmbeddedServletContainerFactory bean that has the same class as the parent context’s EmbeddedServletContainerFactory bean. This ensures that the child context uses the same type of embedded container as its parent when there are multiple embedded containers on the classpath. It also causes a failure when the custom EmbeddedServletContainerFactory subclass cannot be instantiated, for example because it’s an anonymous inner-class. This commit improves the diagnostics so that we fail fast with an information exception message when we detect that the embedded servlet container factory bean’s class cannot be instantiated. Closes gh-6193
1 parent f083447 commit 6c8f8c9

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

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

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

1919
import java.io.IOException;
20+
import java.lang.reflect.Modifier;
2021

2122
import javax.servlet.FilterChain;
2223
import javax.servlet.Servlet;
@@ -28,6 +29,7 @@
2829
import org.apache.commons.logging.LogFactory;
2930

3031
import org.springframework.beans.BeansException;
32+
import org.springframework.beans.FatalBeanException;
3133
import org.springframework.beans.factory.BeanFactory;
3234
import org.springframework.beans.factory.BeanFactoryAware;
3335
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -188,20 +190,38 @@ private void createChildManagementContext() {
188190
private void registerEmbeddedServletContainerFactory(
189191
AnnotationConfigEmbeddedWebApplicationContext childContext) {
190192
try {
191-
EmbeddedServletContainerFactory servletContainerFactory = this.applicationContext
192-
.getBean(EmbeddedServletContainerFactory.class);
193193
ConfigurableListableBeanFactory beanFactory = childContext.getBeanFactory();
194194
if (beanFactory instanceof BeanDefinitionRegistry) {
195195
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
196196
registry.registerBeanDefinition("embeddedServletContainerFactory",
197-
new RootBeanDefinition(servletContainerFactory.getClass()));
197+
new RootBeanDefinition(
198+
determineEmbeddedServletContainerFactoryClass()));
198199
}
199200
}
200201
catch (NoSuchBeanDefinitionException ex) {
201202
// Ignore and assume auto-configuration
202203
}
203204
}
204205

206+
private Class<?> determineEmbeddedServletContainerFactoryClass()
207+
throws NoSuchBeanDefinitionException {
208+
Class<?> servletContainerFactoryClass = this.applicationContext
209+
.getBean(EmbeddedServletContainerFactory.class).getClass();
210+
if (cannotBeInstantiated(servletContainerFactoryClass)) {
211+
throw new FatalBeanException("EmbeddedServletContainerFactory implementation "
212+
+ servletContainerFactoryClass.getName() + " cannot be instantiated. "
213+
+ "To allow a separate management port to be used, a top-level class "
214+
+ "or static inner class should be used instead");
215+
}
216+
return servletContainerFactoryClass;
217+
}
218+
219+
private boolean cannotBeInstantiated(Class<?> clazz) {
220+
return clazz.isLocalClass()
221+
|| (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers()))
222+
|| clazz.isAnonymousClass();
223+
}
224+
205225
/**
206226
* Add an alias for 'local.management.port' that actually resolves using
207227
* 'local.server.port'.

0 commit comments

Comments
 (0)