Bug report

New Spring Boot 3.0.0-RC1 application with Liquibase + GraalVM native build results in the following error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase': Instantiation of supplied bean failed
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1236) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[inventory:6.0.0-RC2]
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1131) ~[inventory:6.0.0-RC2]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:906) ~[inventory:6.0.0-RC2]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[inventory:6.0.0-RC2]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[inventory:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[inventory:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[inventory:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[inventory:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[inventory:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[inventory:3.0.0-RC1]
        at inventory.InventoryApplication.main(InventoryApplication.java:13) ~[inventory:na]
        at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568) ~[inventory:na]
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[na:na]
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[inventory:na]
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:203) ~[na:na]
Caused by: liquibase.exception.UnexpectedLiquibaseException: java.lang.NoSuchMethodException: liquibase.configuration.LiquibaseConfiguration.<init>()
        at liquibase.Scope.getSingleton(Scope.java:329) ~[na:na]
        at liquibase.Scope.getCurrentScope(Scope.java:83) ~[na:na]
        at liquibase.integration.spring.SpringLiquibase.<init>(SpringLiquibase.java:56) ~[inventory:na]
        at org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration.createSpringLiquibase(LiquibaseAutoConfiguration.java:114) ~[inventory:na]
        at org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration.liquibase(LiquibaseAutoConfiguration.java:90) ~[inventory:na]
        at org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration__BeanDefinitions$LiquibaseConfiguration__BeanDefinitions.lambda$getLiquibaseInstanceSupplier$1(LiquibaseAutoConfiguration__BeanDefinitions.java:71) ~[na:na]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[inventory:6.0.0-RC2]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:212) ~[na:na]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:59) ~[inventory:6.0.0-RC2]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:47) ~[inventory:6.0.0-RC2]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:224) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:211) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[inventory:6.0.0-RC2]
        ... 24 common frames omitted
Caused by: java.lang.NoSuchMethodException: liquibase.configuration.LiquibaseConfiguration.<init>()
        at java.base@17.0.5/java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[inventory:na]
        at java.base@17.0.5/java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754) ~[inventory:na]
        at liquibase.Scope.getSingleton(Scope.java:324) ~[na:na]
        ... 37 common frames omitted

How to reproduce: - Go to https://start.spring.io/, choose version 3.0.0 (RC1), Liquibase, JPA and H2 and create the app - Add a simple Liquibase changelog - Run mvn package and then mvn -Pnative -DskipTests native:compile - Run the resulting application and the error will show

Comment From: derkoe

Related issue in the Liquibase project https://github.com/liquibase/liquibase/issues/1552

Comment From: wilkinsona

Thanks for trying the RC. Liquibase isn't expected to work at this time due to its use of reflection that GraalVM has not been told about. Until this is addressed in Liquibase, it will be addressed by https://github.com/oracle/graalvm-reachability-metadata/pull/98.

Comment From: mhalbritter

I've added the hints for Spring Boot's default location here: https://github.com/spring-projects/spring-boot/issues/32926

Comment From: derkoe

@wilkinsona is there a list of Spring Boot technologies/modules currently supporting native-image in the docs?

Comment From: wilkinsona

Not yet. We intend to update https://github.com/spring-projects/spring-boot/wiki/Known-GraalVM-Native-Image-Limitations but haven't yet had time to do so.

Comment From: derkoe

I have currently two entries for that list: 1. Liquibase - here is RuntimeHintsRegistrar for Liquibase fixing this: https://github.com/derkoe/spring-boot-native-test/blob/7f6ba0afc26211ae02f5f64322670fd07037ec1e/src/main/java/bootnative/LiquibaseNativeHints.java 2. Hibernate's @CreationTimestamp and @UpdateTimestamp - here is the RuntimeHintsRegistrar fixing this: https://github.com/derkoe/spring-boot-native-test/blob/7f6ba0afc26211ae02f5f64322670fd07037ec1e/src/main/java/bootnative/HibernateNativeHints.java

Comment From: wilkinsona

Thanks for the links to your hints.

I believe Liquibase will work out of the box once we've upgraded to 0.9.17 of the Native Build Tools. They, by default, use a new version of the reachability metadata that contains @mhalbritter's hints for Liquibase.

If you need additional hints to use Hibernate then that would suggest that the reachability metadata for it is incomplete. Looking at the reflect-config.json, entries for a number of …Generation classes appears to be missing:

  • CreationTimestampGeneration
  • CurrentTimestampGeneration
  • GeneratedAlwaysValueGeneration
  • GeneratedValueGeneration
  • TenantIdGeneration
  • UpdateTimestampGeneration

This assumes that classes referenced from the generatedBy attribute of @ValueGenerationType will always be instantiated using reflection. Do you know if that's the case, @christophstrobl? Also, I wonder if AttributeBinderType and its binder attribute are the same.

Comment From: christophstrobl

@wilkinsona thanks for the heads up. I've opened oracle/graalvm-reachability-metadata#106 to cover both AttributeBinder and AnnotationValueGeneration types which are instantiated reflectively via the PropertyBinder.

Comment From: wilkinsona

Thanks, @christophstrobl!

Comment From: derkoe

For reference:

Liquibase with YAML works out of the box with 3.0.0-RC2.

If you want to use XML you'll have to add the following classes' constructors as native hints: - liquibase.sql.visitor.AppendSqlVisitor.class - liquibase.sql.visitor.PrependSqlVisitor.class - liquibase.sql.visitor.RegExpReplaceSqlVisitor.class - liquibase.sql.visitor.ReplaceSqlVisitor.class

Here is a working example: https://github.com/derkoe/spring-boot-native-test/blob/81652f9326eb4ebd68d2015a897f54af69963704/src/main/java/bootnative/LiquibaseNativeHints.java

Comment From: mhalbritter

@derkoe Thanks! If you want to help, you could contribute those to https://github.com/oracle/graalvm-reachability-metadata