Skip to content

getTypeForFactoryMethod should catch NoClassDefFoundError #33075

Closed
@HzjNeverStop

Description

@HzjNeverStop

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

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions