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 for constructor arguments must cast null indexed argument value #31508

Closed
sbrannen opened this issue Oct 26, 2023 · 1 comment
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Milestone

Comments

@sbrannen
Copy link
Member

Now that #31495 has been resolved, loading the AOT-optimized ApplicationContext for Spr9799XmlConfigTests fails with the following cause.

 java.lang.IllegalArgumentException: ValueHolder must not be null
	at org.springframework.util.Assert.notNull(Assert.java:172) ~[?:?]
	at org.springframework.beans.factory.config.ConstructorArgumentValues.addIndexedArgumentValue(ConstructorArgumentValues.java:111) ~[?:?]
	at org.springframework.web.servlet.handler.MappedInterceptor__TestContext001_BeanDefinitions.getMappedInterceptorBeanDefinition(MappedInterceptor__TestContext001_BeanDefinitions.java:27) ~[?:?]
	at org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests__TestContext001_BeanFactoryRegistrations.registerBeanDefinitions(Spr9799XmlConfigTests__TestContext001_BeanFactoryRegistrations.java:57) ~[?:?]
	at org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests__TestContext001_ApplicationContextInitializer.initialize(Spr9799XmlConfigTests__TestContext001_ApplicationContextInitializer.java:19) ~[?:?]
	at org.springframework.test.context.junit4.spr9799.Spr9799XmlConfigTests__TestContext001_ApplicationContextInitializer.initialize(Spr9799XmlConfigTests__TestContext001_ApplicationContextInitializer.java:13) ~[?:?]
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContextForAotRuntime(AbstractGenericContextLoader.java:170) ~[main/:?]
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContextForAotRuntime(AbstractGenericContextLoader.java:1) ~[main/:?]
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContextForAotRuntime(AbstractDelegatingSmartContextLoader.java:263) ~[main/:?]
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInAotMode(DefaultCacheAwareContextLoaderDelegate.java:255) ~[main/:?]
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:149) ~[main/:?]

Generated Code:

package org.springframework.web.servlet.handler;

import java.lang.String;
import org.springframework.beans.factory.aot.BeanInstanceSupplier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * Bean definitions for {@link MappedInterceptor}.
 */
public class MappedInterceptor__TestContext001_BeanDefinitions {

  // other methods

  /**
   * Get the bean definition for 'mappedInterceptor#0'.
   */
  public static BeanDefinition getMappedInterceptorBeanDefinition() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(MappedInterceptor.class);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, null);
    beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1, ConversionServiceExposingInterceptor__TestContext001_BeanDefinitions.getMappedInterceptorInnerBeanBeanDefinition());
    beanDefinition.setInstanceSupplier(getMappedInterceptorInstanceSupplier());
    return beanDefinition;
  }
}

This line is the source of the exception:

beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, null);

Since addIndexedArgumentValue(...) is overloaded, the compiler picks the variant that accepts a ValueHolder when the second argument is null, and that variant has a notNull check for the ValueHolder.

Updating the code generator so that it generates the following seems to be one way to address this issue.

beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
@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 26, 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 labels Oct 26, 2023
@snicoll snicoll added this to the 6.1.x milestone Oct 26, 2023
@snicoll snicoll self-assigned this Oct 26, 2023
@snicoll snicoll added the in: core Issues in core modules (aop, beans, core, context, expression) label Oct 26, 2023
@snicoll
Copy link
Member

snicoll commented Oct 26, 2023

Those damn overloaded methods.

snicoll added a commit to snicoll/spring-framework that referenced this issue Oct 26, 2023
This commit fixes code generation when an indexed constructor argument
value is null as the method is overloaded and need the value to be
cast to `Object`.

Closes spring-projectsgh-31508
@snicoll snicoll modified the milestones: 6.1.x, 6.1.0 Oct 28, 2023
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: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants