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

<mvc:annotation-driven> should not instantiate bean property values #31472

Closed
sbrannen opened this issue Oct 22, 2023 · 3 comments
Closed

<mvc:annotation-driven> should not instantiate bean property values #31472

sbrannen opened this issue Oct 22, 2023 · 3 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Oct 22, 2023

When using <mvc:annotation-driven /> in XML configuration, AOT processing fails with the following stack trace.

org.springframework.test.context.aot.TestContextAotException: Failed to generate AOT artifacts for test classes [org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests]
	at org.springframework.test.context.aot.TestContextAotGenerator.lambda$10(TestContextAotGenerator.java:294)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
	at org.springframework.util.MultiValueMapAdapter.forEach(MultiValueMapAdapter.java:179)
	at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:253)
	at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:215)
	at org.springframework.test.context.aot.AotIntegrationTests.endToEndTestsForEntireSpringTestModule(AotIntegrationTests.java:151)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.core.test.tools.CompileWithForkedClassLoaderExtension.intercept(CompileWithForkedClassLoaderExtension.java:97)
	at org.springframework.core.test.tools.CompileWithForkedClassLoaderExtension.interceptTestMethod(CompileWithForkedClassLoaderExtension.java:83)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.springframework.test.context.aot.TestContextAotException: Failed to process test class [org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests] for AOT
	at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:331)
	at org.springframework.test.context.aot.TestContextAotGenerator.lambda$10(TestContextAotGenerator.java:286)
	... 10 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for '[Root bean: class [org.springframework.http.converter.ByteArrayHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.StringHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.ResourceHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.ResourceRegionHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.feed.AtomFeedHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.feed.RssChannelHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null, Root bean: class [org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null]' with type org.springframework.beans.factory.support.ManagedList<?>
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:104)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:255)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addPropertyValues(BeanDefinitionPropertiesCodeGenerator.java:212)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:127)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:176)
	at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:81)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$3(BeanDefinitionMethodGenerator.java:176)
	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:169)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:89)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$3(BeanRegistrationsAotContribution.java:90)
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterBeanDefinitionsMethod(BeanRegistrationsAotContribution.java:88)
	at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$1(BeanRegistrationsAotContribution.java:73)
	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:72)
	at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78)
	at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$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.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:328)
	... 11 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for 'Root bean: class [org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null' with type ?
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCodeForElement(BeanDefinitionPropertyValueCodeGenerator.java:113)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCollectionOf(BeanDefinitionPropertyValueCodeGenerator.java:353)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCollectionCode(BeanDefinitionPropertyValueCodeGenerator.java:342)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:336)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:131)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:101)
	... 35 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for 'Generic bean: class [org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null' with type org.springframework.beans.factory.support.GenericBeanDefinition
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:104)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:255)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$15(BeanDefinitionPropertiesCodeGenerator.java:177)
	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:176)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:126)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:176)
	at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:81)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$3(BeanDefinitionMethodGenerator.java:176)
	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:169)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:89)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateValueCode(DefaultBeanRegistrationCodeFragments.java:189)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.lambda$1(DefaultBeanRegistrationCodeFragments.java:175)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$0(BeanDefinitionPropertiesCodeGenerator.java:102)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:131)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCodeForElement(BeanDefinitionPropertyValueCodeGenerator.java:110)
	... 40 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for 'com.fasterxml.jackson.dataformat.smile.SmileFactory@1de0641b' with type com.fasterxml.jackson.dataformat.smile.SmileFactory
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:104)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:255)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.addPropertyValues(BeanDefinitionPropertiesCodeGenerator.java:212)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:127)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:176)
	at org.springframework.beans.factory.aot.BeanRegistrationCodeGenerator.generateCode(BeanRegistrationCodeGenerator.java:81)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.lambda$3(BeanDefinitionMethodGenerator.java:176)
	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:169)
	at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.generateBeanDefinitionMethod(BeanDefinitionMethodGenerator.java:89)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateValueCode(DefaultBeanRegistrationCodeFragments.java:189)
	at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.lambda$1(DefaultBeanRegistrationCodeFragments.java:175)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$0(BeanDefinitionPropertiesCodeGenerator.java:102)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:131)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:101)
	... 59 more
Caused by: java.lang.IllegalArgumentException: Code generation does not support com.fasterxml.jackson.dataformat.smile.SmileFactory
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:136)
	at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:101)
	... 75 more

This can be reproduced by processing Spr9799XmlConfigTests (in spring-test) via AotIntegrationTests#endToEndTestsForEntireSpringTestModule().

The corresponding XML configuration can be viewed in /spring-test/src/test/resources/org/springframework/test/context/junit4/spr9799/Spr9799XmlConfigTests-context.xml.

@sbrannen sbrannen added status: waiting-for-triage An issue we've not yet triaged or decided on theme: aot An issue related to Ahead-of-time processing labels Oct 22, 2023
@snicoll
Copy link
Member

snicoll commented Oct 23, 2023

We can resolve this either way, but it feels to me that we might have a lot of ground to cover to support this consistently. The XML namespace, for better or worse, has used inner beans for this.

@jhoeller for consistency, it looks like this part of the namespace should configure a bean definition whose factory method produces the bean. On the other hand, I can see that the code is straightforward with a simple new with a default constructor. We can't really fallback on that as it would for sure produce incorrect results...

@snicoll snicoll self-assigned this Oct 23, 2023
@snicoll
Copy link
Member

snicoll commented Oct 23, 2023

And CBORFactory is next as the XML parser is using the same trick. I wonder if an attribute for the property value would help here. A bit bloated but, on the other hand, it's a shame we need some custom code generation to call a default constructor.

@snicoll snicoll changed the title Code generation does not support Jackson SmileFactory <mvc:annotation-driven> should not instantiate bean property values Oct 25, 2023
@snicoll snicoll added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on theme: aot An issue related to Ahead-of-time processing labels Oct 25, 2023
@snicoll snicoll added this to the 6.1.0-RC2 milestone Oct 25, 2023
@snicoll snicoll added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Oct 25, 2023
@snicoll
Copy link
Member

snicoll commented Oct 25, 2023

Turns out that it is an inconsistency with the parser. It instantiating a custom class like that in the parser is doing so at the wrong time. This really should be replaced by an inner bean.

@sbrannen sbrannen changed the title <mvc:annotation-driven> should not instantiate bean property values <mvc:annotation-driven> should not instantiate bean property values Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants