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 does not support ApplicationContext #30900

Closed
CrazyHZM opened this issue Jul 17, 2023 · 8 comments
Closed

Code generation does not support ApplicationContext #30900

CrazyHZM opened this issue Jul 17, 2023 · 8 comments
Labels
status: superseded An issue that has been superseded by another

Comments

@CrazyHZM
Copy link

CrazyHZM commented Jul 17, 2023

Repeat step:

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addIndexedArgumentValue(0,applicationContext);
        beanDefinition.setConstructorArgumentValues(constructorArgumentValues);

Affects: 6.0.11


Exception stack

Exception in thread "main" java.lang.IllegalArgumentException: Failed to generate code for 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@56ace400, started on Mon Jul 17 15:41:45 CST 2023' with type org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:102)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:220)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$addConstructorArgumentValues$3(BeanDefinitionPropertiesCodeGenerator.java:171)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
	at java.base/java.util.Collections$UnmodifiableMap.forEach(Collections.java:1553)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addConstructorArgumentValues(BeanDefinitionPropertiesCodeGenerator.java:170)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:122)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:167)
	at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:86)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$generateBeanDefinitionMethod$3(BeanDefinitionMethodGenerator.java:194)
	at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:54)
	at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:112)
	at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:89)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:188)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:109)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$generateRegisterBeanDefinitionsMethod$2(BeanRegistrationsAotContribution.java:93)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterBeanDefinitionsMethod(BeanRegistrationsAotContribution.java:91)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$applyTo$1(BeanRegistrationsAotContribution.java:76)
	at org.springframework.aot.generate.GeneratedMethod.<init>(GeneratedMethod.java:54)
	at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:112)
	at org.springframework.aot.generate.GeneratedMethods.add(GeneratedMethods.java:89)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.applyTo(BeanRegistrationsAotContribution.java:75)
	at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78)
	at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
	at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
	at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
	at org.springframework.context.aot.ContextAotProcessor.performAotProcessing(ContextAotProcessor.java:106)
	at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:84)
	at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
	at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
	at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:80)
Caused by: java.lang.IllegalArgumentException: Code generation does not support org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:134)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:99)
	... 31 more
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 17, 2023
@snicoll
Copy link
Member

snicoll commented Jul 17, 2023

@CrazyHZM thanks for the report but you don't need to add a constructor argument value if you're using autowiring. Autowiring should inject the context just fine. Can you please try that?

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Jul 17, 2023
@CrazyHZM
Copy link
Author

@snicoll
My Bean does not have a parameterless constructor. After removing the constructor argument value, exceptions without parameterless constructors will be thrown. I think aot does not look for constructors based on the autowiring method.

Exception stack:

Exception in thread "main" java.lang.IllegalStateException: No constructor or factory method candidate found for Root bean: class [org.apache.dubbo.config.spring.ServiceBean]; scope=singleton; abstract=false; lazyInit=null; autowire
Mode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null and argument types []
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorOrFactoryMethod(ConstructorResolver.java:947)
at org.springframework.beans.factory.support.RegisteredBean.resolveConstructorOrFactoryMethod(RegisteredBean.java:212)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.(BeanDefinitionMethodGenerator.java:86)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGeneratorFactory.getBeanDefinitionMethodGenerator(BeanDefinitionMethodGeneratorFactory.java:100)
at org.springframework.beans.factory.aot.BeanDefinitionMethodGeneratorFactory.getBeanDefinitionMethodGenerator(BeanDefinitionMethodGeneratorFactory.java:115)
at org.springframework.beans.factory.aot.BeanRegistrationsAotProcessor.processAheadOfTime(BeanRegistrationsAotProcessor.java:49)
at org.springframework.beans.factory.aot.BeanRegistrationsAotProcessor.processAheadOfTime(BeanRegistrationsAotProcessor.java:37)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.getContributions(BeanFactoryInitializationAotContributions.java:67)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.(BeanFactoryInitializationAotContributions.java:49)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.(BeanFactoryInitializationAotContributions.java:44)
at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
at org.springframework.context.aot.ContextAotProcessor.performAotProcessing(ContextAotProcessor.java:106)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:84)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:80)

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jul 18, 2023
@snicoll
Copy link
Member

snicoll commented Jul 18, 2023

My Bean does not have a parameterless constructor.

Yes, it looks like it takes an ApplicationContext. We can't easily write the code that represents an ApplicationContext for obvious reasons.

I think aot does not look for constructors based on the autowiring method.

I think it does for the simple reason it should be the same code as regular runtime with a number of limitations that seems unrelated. Unfortunately, some partial code in text does not make a valid reproducer. If you want support, please take the time to attach a small sample we can run ourselves that reproduces the issue you've described. Thanks.

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jul 18, 2023
@CrazyHZM
Copy link
Author

CrazyHZM commented Jul 18, 2023

@snicoll
Thanks for reply, here's an example:
https://github.com/apache/dubbo-samples/tree/master/1-basic/dubbo-samples-native-image/dubbo-samples-native-image-provider
You can reproduce the problem by running mvn clean install -P native native:compile -D maven.test.skip=true

The ServiceBean is defined here: https://github.com/apache/dubbo/blob/3.2/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jul 18, 2023
@snicoll
Copy link
Member

snicoll commented Jul 18, 2023

Both those links lead to a 404The first link leads to a 404. Please make sure that the sample is as minimal as possible. I shouldn't have to deal with dubbo to reproduce the problem you've described.

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jul 18, 2023
@snicoll
Copy link
Member

snicoll commented Jul 18, 2023

After an edit, I can access the second link. ServiceBean has four constructors and is using a framework feature that determines the constructor to use based on the matching arguments. Unfortunately, this is exactly one of the limitations I was referring to in my previous comment.

AOT doesn't support picking up the "right" constructor based on the available arguments. The runtime has such a feature because it can use the instances that have already been created prior to handling the bean, and instances have full type information. We could try to be best effort and rely on the type signature of the bean definitions but we haven't done this so far as we are considering deprecating this feature at some point.

It looks like you create the bean definition in an attempt for it to use the ApplicationContext argument. A better way to do this is to add @Autowired on the constructor that you want to use. Alternatively, you could have a no-arg constructor since you're implementing ApplicationContextAware already. This isn't confirmed for your particular use case as I don't have a sample I can try but if you're having a hard time creating it, you could give those a try first.

@CrazyHZM
Copy link
Author

Thanks for replying,
Because of the design of ServiceBean, no-arg constructors are not possible, but @Autowired solves the problem of execution in AOT.
@snicoll

@snicoll
Copy link
Member

snicoll commented Jul 20, 2023

Alright, that's good to know. I've created #30917 to try to offer an escape hatch for this use case. There are more options defined here in case you're interested.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Jul 20, 2023
@snicoll snicoll added status: superseded An issue that has been superseded by another and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Jul 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another
Projects
None yet
Development

No branches or pull requests

3 participants