spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.53k stars 38.12k forks source link

`getTypeForFactoryMethod` should catch `NoClassDefFoundError` #33075

Closed HzjNeverStop closed 4 months ago

HzjNeverStop commented 4 months ago

Environment: SpringBoot 3.2.6

In the following scenario, this behavior makes it difficult to locate the root cause of the problem: For example, two Configuration classes A and B register two BeanDefinitions A and B with the same beanName, using @ConditionalOnMissingBean to ensure that only one BeanDefinition is effective.

When another Configuration class C registers a BeanDefinition, and this BeanDefinition uses a class that cannot be found, the following situation may occur:

  1. Configuration class A registers BeanDefinition A;
  2. Configuration class C registers BeanDefinition C;
  3. When Configuration class B registers BeanDefinition B, during the evaluation of the OnBeanCondition getBeanNamesForType process, an empty set array is returned because an exception is thrown while parsing BeanDefinition C in the OnBeanCondition#getBeanNamesForType method.

As a result, the BeanDefinition B registered by Configuration class B is not skipped, causing springboot to throw a BeanDefinitionOverrideException. The root cause exception of the problem is swallowed in the OnBeanCondition#getBeanNamesForType method, making it difficult to locate the problem.

The swallowed stack trace:

java.lang.NoClassDefFoundError: javax/servlet/Filter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
    at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
    at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
    at java.base/sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68)
    at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138)
    at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
    at java.base/sun.reflect.generics.repository.MethodRepository.computeReturnType(MethodRepository.java:75)
    at java.base/sun.reflect.generics.repository.MethodRepository.getReturnType(MethodRepository.java:66)
    at java.base/java.lang.reflect.Method.getGenericReturnType(Method.java:295)
    at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:516)
    at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:297)
    at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:106)
    at org.springframework.core.ResolvableType.forType(ResolvableType.java:1458)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1379)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1361)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1328)
    at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1273)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:817)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:682)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:653)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1687)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:562)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:534)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:247)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:240)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:230)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:183)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:158)
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:183)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:120)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:429)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)

The spring boot failure reason:

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'propertySourcesPlaceholderConfigurer', defined in class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/alipay/sofa/boot/autoconfigure/core/AlipayBootAutoConfiguration$AlipayPropertyPlaceholderAutoConfiguration.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
philwebb commented 4 months ago

@HzjNeverStop Are you able to provide a sample application? I'm having a hard time following the example you're describing. Swallowing the exception is intentional since we assume that if the class isn't available there can be no beans of that type.

HzjNeverStop commented 4 months ago

@HzjNeverStop Are you able to provide a sample application? I'm having a hard time following the example you're describing. Swallowing the exception is intentional since we assume that if the class isn't available there can be no beans of that type.

I tried to reproduce this issue, which occurs when the method return type is a generic structure. You can reproduce this using the github demo (after packaging with mvn package, start the SpringBoot program using java -jar).

wilkinsona commented 4 months ago

Thanks, @HzjNeverStop. Something's definitely wrong here. The sample has:

@AutoConfiguration(before = DemoBAutoConfiguration.class)
public class DemoAAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DemoBean demoBean() {
        return new DemoBean("from DemoAAutoConfiguration");
    }
}

and

@AutoConfiguration
public class DemoBAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public DemoBean demoBean() {
        return new DemoBean("from DemoBAutoConfiguration");
    }
}

Yet both demoBean methods result in the bean being defined. The condition evaluation report shows that no beans of that type were found both times it was evaluated:

   DemoAAutoConfiguration#demoBean matched:
      - @ConditionalOnMissingBean (types: com.example.spring_demo.DemoBean; SearchStrategy: all) did not find any beans (OnBeanCondition)

   DemoBAutoConfiguration#demoBean matched:
      - @ConditionalOnMissingBean (types: com.example.spring_demo.DemoBean; SearchStrategy: all) did not find any beans (OnBeanCondition)

Stack trace of the exception that's swallowed:

java.lang.NoClassDefFoundError: javax/servlet/Filter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:103)
    at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)
    at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
    at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
    at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
    at java.base/sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68)
    at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138)
    at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
    at java.base/sun.reflect.generics.repository.MethodRepository.computeReturnType(MethodRepository.java:75)
    at java.base/sun.reflect.generics.repository.MethodRepository.getReturnType(MethodRepository.java:66)
    at java.base/java.lang.reflect.Method.getGenericReturnType(Method.java:295)
    at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:516)
    at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:297)
    at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:106)
    at org.springframework.core.ResolvableType.forType(ResolvableType.java:1458)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1379)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1361)
    at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1328)
    at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1273)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:817)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:682)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:653)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1687)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:562)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:534)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:247)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:240)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:230)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:183)
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:158)
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:183)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:120)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:429)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:788)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
    at com.example.spring_demo.SpringDemoApplication.main(SpringDemoApplication.java:10)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91)
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53)
    at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58)
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:103)
    at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    ... 66 more
wilkinsona commented 4 months ago

I've tried patching Framework so that AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod catches NoClassDefFoundError and returns null. This seems aligned with its javadoc that states that it will return "the type for the bean if determinable, or null otherwise". With this change in place, the sample then fails like this:

2024-06-20T09:49:47.393+01:00 ERROR 46247 --- [spring-demo] [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean' defined in class path resource [com/example/spring_demo/DemoCAutoConfiguration.class]: Failed to instantiate [org.springframework.boot.web.servlet.FilterRegistrationBean]: Factory method 'errorBean' threw exception with message: javax/servlet/Filter
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:485) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1341) ~[!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1171) ~[!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.8.jar!/:6.1.8]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.8.jar!/:6.1.8]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.6.jar!/:3.2.6]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.6.jar!/:3.2.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.6.jar!/:3.2.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.2.6.jar!/:3.2.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.2.6.jar!/:3.2.6]
    at com.example.spring_demo.SpringDemoApplication.main(SpringDemoApplication.java:10) ~[!/:0.0.1-SNAPSHOT]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.FilterRegistrationBean]: Factory method 'errorBean' threw exception with message: javax/servlet/Filter
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~[spring-beans-6.1.8.jar!/:6.1.8]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.8.jar!/:6.1.8]
    ... 25 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/Filter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017) ~[na:na]
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[na:na]
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524) ~[na:na]
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427) ~[na:na]
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421) ~[na:na]
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) ~[na:na]
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[na:na]
    at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:103) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na]
    at com.example.spring_demo.DemoCAutoConfiguration.errorBean(DemoCAutoConfiguration.java:17) ~[!/:0.0.1-SNAPSHOT]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.8.jar!/:6.1.8]
    ... 26 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[na:na]
    at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:103) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91) ~[spring-demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na]
    ... 44 common frames omitted

I think this is exactly what we want. Unlike the exception above that's swallowed, the failure here precisely pinpoints the cause of the problem as it identifies errorBean as the cause.

We'll transfer this to the Framework team so that they can consider if they want to make a change here.