Affects: 6.1.3


A bean definition that uses non-common value types like this:

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);
        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new MyBeanRecord("Bob", 12));
        registry.registerBeanDefinition("MyBean", beanDefinition);
    }

will cause a ValueCodeGeneration exception. Since this use case is intentionally unsupported (see https://github.com/spring-projects/spring-framework/issues/32214#issuecomment-1933482152), a helpful error message saying "ConstructorArgumentValues do not support code generation for arguments of type (MyBeanRecord)" should be thrown instead, similar to what happens with instance suppliers.

Demo: https://github.com/Christopher-Chianelli/issue-reproducer/tree/constructor-argument-value-unsupported/demo

Comment From: snicoll

It's not really the same thing. The issue you've referenced is a limitation of a supported construct of the core container. Creating a bean definition with an instance supplier is totally supported but, for obvious reasons, can't be supported by the AOT engine.

Providing complex object structure to a BeanDefinition is not idiomatic at all. The bean definition is an abstraction on top of several models, including our XML namespace where you can't obviously pass such an object. The idiomatic way to provide such object is via factory, or a bean reference.

"ConstructorArgumentValues do not support code generation for arguments of type (MyBeanRecord)" should be thrown instead, similar to https://github.com/spring-projects/spring-framework/issues/29556.

I disagree with that. There's nothing specific with ConstructorArgumentValues here. That being said, I can see how the ultimate exception thrown at the user can be rephrased by referencing to what I've just explained.

Comment From: snicoll

With the work going on in #32777 this will generate the following:

org.springframework.beans.factory.aot.AotBeanProcessingFailedException: Error processing bean with name 'MyBean': failed to generate code for bean definition

    at org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.lambda$generateRegisterBeanDefinitionsMethod$2(BeanRegistrationsAotContribution.java:101)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    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.beans.factory.aot.BeanRegistrationsAotContributionTests.applyToFailingWrapsValueCodeGeneration2(BeanRegistrationsAotContributionTests.java:205)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.springframework.aot.generate.ValueCodeGenerationException: Failed to generate code for 'MyBeanRecord[name=Bob, age=12]' with type class com.example.MyBeanRecord
    at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:116)
    at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateValue(BeanDefinitionPropertiesCodeGenerator.java:269)
    at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.lambda$addConstructorArgumentValues$3(BeanDefinitionPropertiesCodeGenerator.java:191)
    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:188)
    at org.springframework.beans.factory.aot.BeanDefinitionPropertiesCodeGenerator.generateCode(BeanDefinitionPropertiesCodeGenerator.java:134)
    at org.springframework.beans.factory.aot.DefaultBeanRegistrationCodeFragments.generateSetBeanDefinitionPropertiesCode(DefaultBeanRegistrationCodeFragments.java:180)
    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:91)
    ... 11 more
Caused by: org.springframework.aot.generate.UnsupportedTypeValueCodeGenerationException: Code generation does not support com.example.MyBeanRecord
    at org.springframework.aot.generate.ValueCodeGenerator.generateCode(ValueCodeGenerator.java:113)
    ... 26 more

Let's rephrase this to have a section in the reference doc that rather explains why this exception is thrown. Conveying that in the exception message is not really practical.