Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code generation no longer supports a list of inner BeanDefinitions #29075

Closed
sbrannen opened this issue Sep 5, 2022 · 5 comments
Closed

Code generation no longer supports a list of inner BeanDefinitions #29075

sbrannen opened this issue Sep 5, 2022 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: regression A bug that is also a regression
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Sep 5, 2022

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

@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement theme: aot An issue related to Ahead-of-time processing labels Sep 5, 2022
@sbrannen sbrannen added this to the 6.0.0-M6 milestone Sep 5, 2022
@snicoll
Copy link
Member

snicoll commented Sep 7, 2022

@sbrannen How can I reproduce this?

@sbrannen
Copy link
Member Author

sbrannen commented Sep 7, 2022

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));
}

@snicoll
Copy link
Member

snicoll commented Sep 8, 2022

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.

@snicoll snicoll self-assigned this Sep 8, 2022
@snicoll
Copy link
Member

snicoll commented Sep 8, 2022

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.

@snicoll snicoll added type: regression A bug that is also a regression and removed type: enhancement A general enhancement labels Sep 8, 2022
@snicoll snicoll changed the title Unresolved ResolvableType encountered in BeanDefinitionPropertyValueCodeGenerator Code generation does no longer support list of BeanDefinitions Sep 8, 2022
@sbrannen sbrannen changed the title Code generation does no longer support list of BeanDefinitions Code generation no longer supports a list of BeanDefinitions Sep 8, 2022
@snicoll
Copy link
Member

snicoll commented Sep 8, 2022

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.

@snicoll snicoll modified the milestones: 6.0.0-M6, 6.0.0-RC1 Sep 12, 2022
@snicoll snicoll modified the milestones: 6.0.0-RC1, 6.0.0-RC2 Oct 10, 2022
@snicoll snicoll changed the title Code generation no longer supports a list of BeanDefinitions Code generation no longer supports a list of inner BeanDefinitions Oct 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

2 participants