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

Support TypedStringValue during AOT processing #29074

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

Support TypedStringValue during AOT processing #29074

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: enhancement A general enhancement
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Sep 5, 2022

Overview

When BeanDefinitionPropertyValueCodeGenerator.MapDelegate generates code for a Map, that map may contain instances of TypedStringValue resulting in a stack trace similar to the following that occurred while processing an ApplicationContext created from ExpressionUsageTests-context.xml in spring-test. We should likely replace typed string values with actual values before generating the map.

Caused by: java.lang.ClassCastException: class org.springframework.beans.factory.config.TypedStringValue cannot be cast to class java.lang.Comparable (org.springframework.beans.factory.config.TypedStringValue is in unnamed module of loader org.springframework.aot.test.generator.compile.CompileWithTargetClassAccessClassLoader @24a1c17f; java.lang.Comparable is in module java.base of loader 'bootstrap')
	at java.util.TreeMap.compare(TreeMap.java:1569) ~[?:?]
	at java.util.TreeMap.addEntryToEmptyMap(TreeMap.java:776) ~[?:?]
	at java.util.TreeMap.put(TreeMap.java:785) ~[?:?]
	at java.util.TreeMap.put(TreeMap.java:534) ~[?:?]
	at java.util.AbstractMap.putAll(AbstractMap.java:281) ~[?:?]
	at java.util.TreeMap.putAll(TreeMap.java:326) ~[?:?]
	at java.util.TreeMap.<init>(TreeMap.java:187) ~[?:?]
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$MapDelegate.orderForCodeConsistency(BeanDefinitionPropertyValueCodeGenerator.java:497) ~[main/:?]
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$MapDelegate.generateMapCode(BeanDefinitionPropertyValueCodeGenerator.java:471) ~[main/:?]
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$MapDelegate.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:457) ~[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:115) ~[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/:?]

BeanDefinitionPropertyValueCodeGenerator may need a TypedStringValueDelegate (or similar), because without one we see stack traces similar to the following that occurred while processing an ApplicationContext created from SpringJUnit4ClassRunnerAppCtxTests-context.xml in spring-test.

Caused by: java.lang.IllegalArgumentException: 'type' org.springframework.beans.factory.config.TypedStringValue must be supported for instance code generation
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:102) ~[main/:?]
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:89) ~[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.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 6, 2022

There's also the problem that ConstructorOrFactoryMethodResolver isn't resolving TypedStringValue at the moment. When computing the arguments to use to identify a matching constructor, it takes the raw TypedStringValue.

This is one more case that links to #27920

@snicoll
Copy link
Member

snicoll commented Sep 9, 2022

I am not yet convinced that we have to handle TypedStringValue like that. Rather I was hoping that the resolved constructor would give us the arguments needed, and the generator would write an indexed argument.

@snicoll
Copy link
Member

snicoll commented Sep 27, 2022

Blocked by #27920

@snicoll snicoll added the status: blocked An issue that's blocked on an external project change label Sep 27, 2022
@snicoll snicoll modified the milestones: 6.0.0-RC1, 6.0.x Oct 10, 2022
@sdeleuze sdeleuze removed the status: blocked An issue that's blocked on an external project change label Feb 21, 2023
@sdeleuze sdeleuze modified the milestones: 6.0.x, 6.1.x Feb 21, 2023
@ganapathi004
Copy link

Any known workaround until the support is added? We are trying to convert one of our projects with XML configuration to Spring Boot 3 Native Image.

@snicoll snicoll self-assigned this Aug 31, 2023
@sbrannen sbrannen changed the title Support TypedStringValue during AOT processing Support TypedStringValue during AOT processing Oct 12, 2023
@snicoll snicoll modified the milestones: 6.1.x, 6.1.0-RC2 Oct 12, 2023
@snicoll
Copy link
Member

snicoll commented Oct 12, 2023

We've made quite a bit of progress in better support for XML configs but there is still one major point to review, see #31420. Please keep testing against the latest version, thanks!

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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants