spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.
https://spring.io/projects/spring-data
Apache License 2.0
769 stars 669 forks source link

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

Closed nkonev closed 1 year ago

nkonev commented 1 year ago

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)

Converted from https://github.com/spring-projects/spring-boot/issues/33352


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

FYI: I've created a smoke test which uses data-jdbc with kotlin: https://github.com/spring-projects/spring-aot-smoke-tests/tree/main/data/data-jdbc-h2-kotlin

christophstrobl commented 1 year ago

@sdeleuze I think we should fix this in framework (BindingReflectionHintsRegistrar) and include queryAllDeclaredMethods for types eligible for data binding. Along with adding copy$default for Kotlin types (see: issues/2738) this should fix the issue.

sdeleuze commented 1 year ago

Ok, I will handle it as part of #29593.

mp911de commented 1 year ago

Will be fixed via https://github.com/spring-projects/spring-framework/issues/29593.