After upgrade to Spring Boot 3.2, AOT failure "Code generation does not support ?"

852 views Asked by At

I've recently upgraded my app to Spring Boot 3.2 and Java 21. We use Spring Data JDBC and have tests that mock our repositories with @MockBean. After upgrading, when I run ./gradlew build I get this failure. The tests are all failing during the AOT code generation phase with this error.

Exception in thread "main" org.springframework.test.context.aot.TestContextAotException: Failed to generate AOT artifacts for test classes [<list of our classes>]
        at org.springframework.test.context.aot.TestContextAotGenerator.lambda$processAheadOfTime$5(TestContextAotGenerator.java:285)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:986)
        at org.springframework.util.MultiValueMapAdapter.forEach(MultiValueMapAdapter.java:179)
        at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:243)
        at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:205)
        at org.springframework.test.context.aot.TestAotProcessor.performAotProcessing(TestAotProcessor.java:91)
        at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:72)
        at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:39)
        at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
        at org.springframework.boot.test.context.SpringBootTestAotProcessor.main(SpringBootTestAotProcessor.java:63)
Caused by: org.springframework.test.context.aot.TestContextAotException: Failed to process test class [<failing test class>] for AOT
        at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:322)
        at org.springframework.test.context.aot.TestContextAotGenerator.lambda$processAheadOfTime$5(TestContextAotGenerator.java:276)
        ... 9 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for '[[MockDefinition@5b5f61cc name = '', typeToMock = <Spring Data JDBC repository being mocked>, extraInterfaces = set[[empty]], answer = RETURNS_DEFAULTS, serializable = false, reset = AFTER]]' with type java.util.LinkedHashSet<?>
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:105)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:257)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$addConstructorArgumentValues$3(BeanDefinitionPropertiesCodeGenerator.java:179)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:986)
        at java.base/java.util.Collections$UnmodifiableMap.forEach(Collections.java:1707)
        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$generateBeanDefinitionMethod$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$generateRegisterBeanDefinitionsMethod$2(BeanRegistrationsAotContribution.java:90)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:986)
        at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.generateRegisterBeanDefinitionsMethod(BeanRegistrationsAotContribution.java:88)
        at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$applyTo$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$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.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:318)
        ... 10 more
Caused by: java.lang.IllegalArgumentException: Failed to generate code for '[MockDefinition@5b5f61cc name = '', typeToMock = <Spring Data JDBC repository being mocked>, extraInterfaces = set[[empty]], answer = RETURNS_DEFAULTS, serializable = false, reset = AFTER]' with type ?
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCodeForElement(BeanDefinitionPropertyValueCodeGenerator.java:114)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCollectionOf(BeanDefinitionPropertyValueCodeGenerator.java:351)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$SetDelegate.generateCollectionCode(BeanDefinitionPropertyValueCodeGenerator.java:450)

> Task :processTestAot FAILED
10 actionable tasks: 1 executed, 9 up-to-date
      at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$SetDelegate.generateCollectionCode(BeanDefinitionPropertyValueCodeGenerator.java:440)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator$CollectionDelegate.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:334)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:132)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:102)
        ... 37 more
Caused by: java.lang.IllegalArgumentException: Code generation does not support ?
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCode(BeanDefinitionPropertyValueCodeGenerator.java:137)
        at org.springframework.beans.factory.aot.BeanDefinitionPropertyValueCodeGenerator.generateCodeForElement(BeanDefinitionPropertyValueCodeGenerator.java:111)
        ... 43 more

It seems to be triggered by the @MockBean entry. If I comment out that type, then I can get a clean build.

I don't know where that ? is coming from as none of my repository types are using that. They are all pretty standard types, like...

public interface FooRepository extends ListCrudRepository<Foo, UUID>, PagingAndSortingRepository<Foo, UUID> {
}

Looking for ways to fix this, or at least work around the issue. Thanks

1

There are 1 answers

4
Maria Svorenova On

I get the same exception for my test, but only when run with Gradle, not Maven (no idea why that matters though..).

The issue for me was caused by the fact that I had tests with @DisabledInAotMode annotation and according to the documentation of that annotation:

If a test class is annotated with @DisabledInAotMode, all other test classes which specify configuration to load the same ApplicationContext must also be annotated with @DisabledInAotMode. Failure to annotate all such test classes will result in an exception, either at build time or run time.

Once I added @DisabledInAotMode to the test class that originally threw the exception it resolved the issue and all tests pass.

UPDATE: Actually it's even simpler - every test class that contains @MockBean needs @DisabledInAotMode annotation (regardless of what's happening in any other test classes), in a Gradle project and if you're using Spring Core 6.1.0+ (Spring Boot 3.2+).