spring 对于GraalVM上的数据类,带Kotlin的Sping Boot 3抛出java.lang.UnsupportedOperationException异常

4c8rllxm  于 2022-12-10  发布在  Spring
关注(0)|答案(1)|浏览(145)

尝试在GraalVM上运行一个非常简单的Sping Boot 3应用程序。该应用程序只是在启动时将一些数据存储在H2中。它基本上与Josh在Spring Tips about Ahead-of-Time compilation中所做的相同,但使用的是Kotlin而不是Java。
当启动本机映像时,我在Spring启动后收到以下错误:

java.lang.UnsupportedOperationException: Kotlin class com.example.demo.basics.Customer has no .copy(…) method for property id
        at org.springframework.data.mapping.model.BeanWrapper$KotlinCopyUtil.setProperty(BeanWrapper.java:171) ~[na:na]
        at org.springframework.data.mapping.model.BeanWrapper.setProperty(BeanWrapper.java:79) ~[na:na]
...

我对GraalVM和Spring原生映像还很陌生,不知道我是否遗漏了一些基本的东西,在使用Kotlin和Spring时需要配置。数据类的复制方法应该是由Kotlin生成的,所以我猜一些东西是由与Kotlin相关的原生编译遗漏的。
失败的代码是以下类:

@Configuration
class BasicsConfiguration {
    @Bean // execute on application start
    fun basicsApplicationListener(customerRepository: CustomerRepository): ApplicationListener<ApplicationReadyEvent> {
        return ApplicationListener<ApplicationReadyEvent> {
            // store some values in the database
            customerRepository
                .saveAll(listOf("A", "B", "C").map { Customer(null, it) })
                .forEach { println(it) }
        }
    }
}

interface CustomerRepository : CrudRepository<Customer, Int>

data class Customer(@Id val id: Long?, val name: String)

在JDK上运行应用程序可以很好地工作:./gradlew bootRun

2022-11-30T11:23:15.300+01:00  INFO 33997 --- [           main] com.example.demo.DemoApplicationKt       : Started DemoApplicationKt in 2.383 seconds (process running for 2.733)
Customer(id=1, name=A)
Customer(id=2, name=B)
Customer(id=3, name=C)

本机映像也将成功创建:./gradlew nativeCompile
启动本机映像正常,服务器进程启动,但随后失败:

2022-11-30T11:08:11.085+01:00  INFO 33059 --- [           main] com.example.demo.DemoApplicationKt       : Started DemoApplicationKt in 0.147 seconds (process running for 0.158)
2022-11-30T11:08:11.089+01:00 ERROR 33059 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.UnsupportedOperationException: Kotlin class com.example.demo.basics.Customer has no .copy(…) method for property id
        at org.springframework.data.mapping.model.BeanWrapper$KotlinCopyUtil.setProperty(BeanWrapper.java:171) ~[na:na]
        at org.springframework.data.mapping.model.BeanWrapper.setProperty(BeanWrapper.java:79) ~[na:na]
...
k97glaaz

k97glaaz1#

看起来这是Spring Data的问题,它没有为本地映像创建提供所有必要的反射提示。特别是缺少数据类的copy$default方法的反射配置。将(可能)在Spring 6.0.3版本中修复,请参阅此问题以了解详细信息:https://github.com/spring-projects/spring-framework/issues/29593
解决方法:在reflect-config.json中为给定的数据类添加类似如下的内容:

{
        "name": "copy$default",
        "parameterTypes": [
          "com.example.demo.basics.Customer",
          "java.lang.Long",
          "java.lang.String",
          "int",
          "java.lang.Object"
        ]
      }

相关问题