Commit 6c8f8c9d authored by Andy Wilkinson's avatar Andy Wilkinson

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
parent f083447a
......@@ -17,6 +17,7 @@
package org.springframework.boot.actuate.autoconfigure;
import java.io.IOException;
import java.lang.reflect.Modifier;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
......@@ -28,6 +29,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
......@@ -188,13 +190,12 @@ public class EndpointWebMvcAutoConfiguration
private void registerEmbeddedServletContainerFactory(
AnnotationConfigEmbeddedWebApplicationContext childContext) {
try {
EmbeddedServletContainerFactory servletContainerFactory = this.applicationContext
.getBean(EmbeddedServletContainerFactory.class);
ConfigurableListableBeanFactory beanFactory = childContext.getBeanFactory();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
registry.registerBeanDefinition("embeddedServletContainerFactory",
new RootBeanDefinition(servletContainerFactory.getClass()));
new RootBeanDefinition(
determineEmbeddedServletContainerFactoryClass()));
}
}
catch (NoSuchBeanDefinitionException ex) {
......@@ -202,6 +203,25 @@ public class EndpointWebMvcAutoConfiguration
}
}
private Class<?> determineEmbeddedServletContainerFactoryClass()
throws NoSuchBeanDefinitionException {
Class<?> servletContainerFactoryClass = this.applicationContext
.getBean(EmbeddedServletContainerFactory.class).getClass();
if (cannotBeInstantiated(servletContainerFactoryClass)) {
throw new FatalBeanException("EmbeddedServletContainerFactory implementation "
+ servletContainerFactoryClass.getName() + " cannot be instantiated. "
+ "To allow a separate management port to be used, a top-level class "
+ "or static inner class should be used instead");
}
return servletContainerFactoryClass;
}
private boolean cannotBeInstantiated(Class<?> clazz) {
return clazz.isLocalClass()
|| (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers()))
|| clazz.isAnonymousClass();
}
/**
* Add an alias for 'local.management.port' that actually resolves using
* 'local.server.port'.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment