Overview
An unresolved ResolvableType
in BeanDefinitionPropertyValueCodeGenerator
results in a stack trace similar to the following that occurred while processing an ApplicationContext
created from transactionalTests-context.xml
in spring-test
.
Caused by: java.lang.IllegalArgumentException: 'type' ? must be supported for instance code generation
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:103) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCollectionOf(BeanDefinitionPropertyValueCodeGenerator.java:326) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCollectionCode(BeanDefinitionPropertyValueCodeGenerator.java:315) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:309) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:98) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:90) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addPropertyValues(BeanDefinitionPropertiesCodeGenerator.java:182) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:128) ~[main/:?]
at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:144) ~[main/:?]
at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:86) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$2(BeanDefinitionMethodGenerator.java:149) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:48) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:85) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:72) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:143) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:107) ~[main/:?]
at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateValueCode(DefaultBeanRegistrationCodeFragments.java:157) ~[main/:?]
at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.lambda$0(DefaultBeanRegistrationCodeFragments.java:143) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addPropertyValues(BeanDefinitionPropertiesCodeGenerator.java:180) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:128) ~[main/:?]
at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:144) ~[main/:?]
at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:86) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$2(BeanDefinitionMethodGenerator.java:149) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:48) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:85) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:72) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:143) ~[main/:?]
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:107) ~[main/:?]
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$2(BeanRegistrationsAotContribution.java:83) ~[main/:?]
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[?:?]
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterMethod(BeanRegistrationsAotContribution.java:81) ~[main/:?]
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$1(BeanRegistrationsAotContribution.java:67) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:48) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:85) ~[main/:?]
at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:72) ~[main/:?]
at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.applyTo(BeanRegistrationsAotContribution.java:66) ~[main/:?]
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78) ~[main/:?]
at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$0(ApplicationContextAotGenerator.java:58) ~[main/:?]
at org.springframework.context.aot.ApplicationContextAotGenerator.withGeneratedClassHandler(ApplicationContextAotGenerator.java:66) ~[main/:?]
at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53) ~[main/:?]
at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:149) ~[main/:?]
Related Issues
-
29013
Comment From: snicoll
@sbrannen How can I reproduce this?
Comment From: sbrannen
Running the following in spring-test
will reproduce it.
public static void main(String[] args) {
GeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
generator.processAheadOfTime(Stream.of(MethodLevelTransactionalSpringRunnerTests.class));
}
Comment From: snicoll
Thanks Sam. The problem is that we need to write a ManagedList
for CompositeDatabasePopulator
and the type of the elements is unknown. I'll see what I can do to support that use case and improve the exception message regardless.
Comment From: snicoll
Let me take this back. This is much simpler. There is a list of inner bean definitions and the code currently doesn't support that. It only support the case where a property or an attribute is a bean definition. Looking at the code, I don't understand why the extra delegate isn't passed to BeanDefinitionPropertyValueCodeGenerator
. We used to have a innerBeanDefinitionWriter
that was taking care of this to be able to reused in case of a collection.
Comment From: snicoll
I've been spending a few hours on this and I need some help. My attempt is at https://github.com/snicoll/spring-framework/tree/gh-29075.
I've tried to prevent the name
of the constructor argument or attribute to be mandatory but that led to some unpleasant code. My thinking is that BeanDefinitionPropertyValueCodeGenerator
must be able to handle bean definitions, provided with a custom writer (previous arrangement, for reference). To still transmit the name, I was thinking of wrapping the BeanDefinition
in some sort of container, that the custom generator could detect.
This is working but it is extra hard for collections as the generator itself loops over them. If the original value is a collection, you have to create a copy that does the wrapping upfront, with ManagedList
& co.
I am also confused about RegisteredBean#isGeneratedBeanName
. If we manage to make this work, then BeanDefinitionMethodGenerator
no longer needs a @Nullable
innerBeanName.