spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.67k stars 40.58k forks source link

Spring Boot 3 native-image: Kotlin Could not compute caller for function #33352

Closed nkonev closed 1 year ago

nkonev commented 1 year ago

Potentially it's very similar to https://github.com/spring-projects/spring-boot/issues/33351

Reproducer:

git clone git@github.com:nkonev/web-jdbc-flyway-native.git
cd web-jdbc-flyway-native
./gradlew clean bootBuildImage
docker-compose up -d
docker run --network=host --rm -p 8080:8080 docker.io/library/web-jdbc-native:0.0.1-SNAPSHOT

The error will be like

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'branchRepository': Could not compute caller for function: public final fun addSubject(subject: name.nkonev.example.webjdbcnative.Subject): kotlin.Unit defined in name.nkonev.example.webjdbcnative.Branch[DeserializedSimpleFunctionDescriptor@281863cb] (member = null)
mhalbritter commented 1 year ago

That's the full stacktrace:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appRunner': Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'branchRepository': Could not compute caller for function: public final fun addSubject(subject: name.nkonev.example.webjdbcnative.Subject): kotlin.Unit defined in name.nkonev.example.webjdbcnative.Branch[DeserializedSimpleFunctionDescriptor@7f83f5ba] (member = null)
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:351) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:271) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:206) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[web-jdbc-native:6.0.2]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[web-jdbc-native:6.0.2]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[web-jdbc-native:6.0.2]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[web-jdbc-native:3.0.0]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[web-jdbc-native:3.0.0]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[web-jdbc-native:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[web-jdbc-native:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[web-jdbc-native:3.0.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[web-jdbc-native:3.0.0]
        at name.nkonev.example.webjdbcnative.WebJdbcNativeApplicationKt.main(WebJdbcNativeApplication.kt:59) ~[web-jdbc-native:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'branchRepository': Could not compute caller for function: public final fun addSubject(subject: name.nkonev.example.webjdbcnative.Subject): kotlin.Unit defined in name.nkonev.example.webjdbcnative.Branch[DeserializedSimpleFunctionDescriptor@7f83f5ba] (member = null)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:334) ~[na:na]
        ... 21 common frames omitted
Caused by: kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public final fun addSubject(subject: name.nkonev.example.webjdbcnative.Subject): kotlin.Unit defined in name.nkonev.example.webjdbcnative.Branch[DeserializedSimpleFunctionDescriptor@7f83f5ba] (member = null)
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:88) ~[na:na]
        at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(KFunctionImpl.kt:61) ~[na:na]
        at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:63) ~[na:na]
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32) ~[web-jdbc-native:1.7.21-release-272(1.7.21)]
        at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(KFunctionImpl.kt:61) ~[na:na]
        at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(ReflectJvmMapping.kt:63) ~[na:na]
        at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:136) ~[na:na]
        at org.springframework.core.MethodParameter$KotlinDelegate.getGenericReturnType(MethodParameter.java:914) ~[na:na]
        at org.springframework.core.MethodParameter.getGenericParameterType(MethodParameter.java:510) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider.getType(SerializableTypeWrapper.java:291) ~[na:na]
        at org.springframework.core.SerializableTypeWrapper.forTypeProvider(SerializableTypeWrapper.java:107) ~[na:na]
        at org.springframework.core.ResolvableType.forType(ResolvableType.java:1413) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1334) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1316) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.ResolvableType.forMethodParameter(ResolvableType.java:1283) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.ResolvableType.forMethodReturnType(ResolvableType.java:1243) ~[web-jdbc-native:6.0.2]
        at org.springframework.core.GenericTypeResolver.resolveReturnType(GenericTypeResolver.java:80) ~[na:na]
        at org.springframework.beans.GenericTypeAwarePropertyDescriptor.<init>(GenericTypeAwarePropertyDescriptor.java:110) ~[na:na]
        at org.springframework.beans.CachedIntrospectionResults.buildGenericTypeAwarePropertyDescriptor(CachedIntrospectionResults.java:406) ~[na:na]
        at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:283) ~[na:na]
        at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:158) ~[na:na]
        at org.springframework.beans.BeanUtils.getPropertyDescriptors(BeanUtils.java:489) ~[na:na]
        at org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity(AbstractMappingContext.java:414) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:379) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:280) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:206) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:92) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$6(RepositoryFactoryBeanSupport.java:282) ~[web-jdbc-native:3.0.0]
        at java.base@17.0.5/java.util.Optional.ifPresent(Optional.java:178) ~[web-jdbc-native:na]
        at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:282) ~[web-jdbc-native:3.0.0]
        at org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean.afterPropertiesSet(JdbcRepositoryFactoryBean.java:201) ~[web-jdbc-native:3.0.0]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) ~[web-jdbc-native:6.0.2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) ~[web-jdbc-native:6.0.2]
        ... 31 common frames omitted
mhalbritter commented 1 year ago

When registering all the methods on Branch with this:

class MyRuntimeHints: RuntimeHintsRegistrar {
    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        ReflectionUtils.doWithMethods(Branch::class.java) { method ->
            hints.reflection().registerMethod(method, ExecutableMode.INVOKE)
        }
    }
}

it throws the same error as in #33351. It looks like we need more reflection metadata on types on which org.springframework.beans.BeanUtils.getPropertyDescriptors is called.

mhalbritter commented 1 year ago

As it's org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity who's calling the method, this is a Spring Data issue. @nkonev Could you please file an issue on the Spring Data project? Feel free to link to that issue. Thanks!