spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Missing hints for org.hibernate.generator.Generator

Open ilharp opened this issue 1 month ago • 3 comments

Hibernate cannot instantiate generator in native image due to missing hints.

Environment

  • Spring Boot v3.1.5
  • Spring Framework / Spring Web MVC v6.0.13
  • Hibernate v6.2.13.Final
  • GraalVM Community v17.0.9-20231024

Step to Reproduce

Create an entity with fields annotated with one of org.hibernate.generator.Generator:

@GenericGenerator(name = "xxx", strategy = "xxx")
@GenericGenerator(name = "xxx", type = xxx)
@CreationTimestamp

Logs

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.1.5)

2024-05-19T19:56:16.475Z  INFO 1 --- [           main] com.ilharper.str.host.MainKt             : Starting AOT-processed MainKt using Java 17.0.9 with PID 1 (/app/host started by root in /app)
2024-05-19T19:56:16.475Z  INFO 1 --- [           main] com.ilharper.str.host.MainKt             : No active profile set, falling back to 1 default profile: "default"
2024-05-19T19:56:16.528Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9011 (http)
2024-05-19T19:56:16.529Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-05-19T19:56:16.529Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.15]
2024-05-19T19:56:16.537Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-05-19T19:56:16.537Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 62 ms
2024-05-19T19:56:16.622Z  INFO 1 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2024-05-19T19:56:16.624Z  INFO 1 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.2.13.Final
2024-05-19T19:56:16.624Z  WARN 1 --- [           main] org.hibernate.orm.deprecation            : HHH90000029: The [hibernate.bytecode.use_reflection_optimizer] configuration is deprecated and will be removed. Set the value to [true] to get rid of this warning
2024-05-19T19:56:16.630Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-05-19T19:56:16.746Z  INFO 1 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@17dc1ec
2024-05-19T19:56:16.746Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-05-19T19:56:16.764Z  WARN 1 --- [           main] org.hibernate.orm.deprecation            : HHH90000025: MySQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
2024-05-19T19:56:16.783Z ERROR 1 --- [           main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Could not instantiate generator of type 'org.hibernate.generator.internal.CurrentTimestampGeneration'
2024-05-19T19:56:16.783Z  WARN 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Could not instantiate generator of type 'org.hibernate.generator.internal.CurrentTimestampGeneration'
2024-05-19T19:56:16.783Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-05-19T19:56:16.791Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2024-05-19T19:56:16.792Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2024-05-19T19:56:16.792Z ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Could not instantiate generator of type 'org.hibernate.generator.internal.CurrentTimestampGeneration'
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[host:6.0.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[host:6.0.13]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1166) ~[host:6.0.13]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:940) ~[host:6.0.13]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616) ~[host:6.0.13]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[host:3.1.5]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:738) ~[host:3.1.5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:440) ~[host:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[host:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[host:3.1.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[host:3.1.5]
    at com.ilharper.str.host.MainKt.main(Main.kt:36) ~[host:na]
Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Could not instantiate generator of type 'org.hibernate.generator.internal.CurrentTimestampGeneration'
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[host:na]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[host:na]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[host:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) ~[host:6.0.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[host:6.0.13]
    ... 16 common frames omitted
Caused by: org.hibernate.HibernateException: Could not instantiate generator of type 'org.hibernate.generator.internal.CurrentTimestampGeneration'
    at org.hibernate.boot.model.internal.GeneratorBinder.instantiateGenerator(GeneratorBinder.java:425) ~[na:na]
    at org.hibernate.boot.model.internal.GeneratorBinder.lambda$generatorCreator$0(GeneratorBinder.java:362) ~[na:na]
    at org.hibernate.mapping.Property.createGenerator(Property.java:482) ~[host:6.2.13.Final]
    at org.hibernate.tuple.entity.EntityMetamodel.buildGenerator(EntityMetamodel.java:479) ~[na:na]
    at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:313) ~[na:na]
    at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:502) ~[host:6.2.13.Final]
    at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:140) ~[host:6.2.13.Final]
    at [email protected]/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[host:na]
    at [email protected]/java.lang.reflect.Constructor.newInstance(Constructor.java:480) ~[host:na]
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:92) ~[host:6.2.13.Final]
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:75) ~[host:6.2.13.Final]
    at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.processBootEntities(MappingMetamodelImpl.java:247) ~[na:na]
    at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.finishInitialization(MappingMetamodelImpl.java:185) ~[na:na]
    at org.hibernate.internal.SessionFactoryImpl.initializeMappingModel(SessionFactoryImpl.java:321) ~[na:na]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:271) ~[na:na]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[na:na]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1458) ~[na:na]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[na:na]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[host:na]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[host:na]
    ... 20 common frames omitted
Caused by: java.lang.InstantiationException: org.hibernate.generator.internal.CurrentTimestampGeneration
    at [email protected]/java.lang.Class.newInstance(DynamicHub.java:639) ~[host:na]
    at org.hibernate.boot.model.internal.GeneratorBinder.instantiateGenerator(GeneratorBinder.java:419) ~[na:na]
    ... 39 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.hibernate.generator.internal.CurrentTimestampGeneration.<init>()
    at [email protected]/java.lang.Class.checkMethod(DynamicHub.java:1038) ~[host:na]
    at [email protected]/java.lang.Class.getConstructor0(DynamicHub.java:1204) ~[host:na]
    at [email protected]/java.lang.Class.newInstance(DynamicHub.java:626) ~[host:na]
    ... 40 common frames omitted

Temporary Workaround

package com.ilharper.str.common.aot.hint

import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
import org.hibernate.generator.internal.CurrentTimestampGeneration
import org.springframework.aot.hint.MemberCategory
import org.springframework.aot.hint.RuntimeHints
import org.springframework.aot.hint.RuntimeHintsRegistrar
import org.springframework.aot.hint.TypeHint
import org.springframework.aot.hint.TypeReference
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.ImportRuntimeHints

@Configuration
@ImportRuntimeHints(HibernateGeneratorRegistrar::class)
class HibernateRuntimeHints

class HibernateGeneratorRegistrar : RuntimeHintsRegistrar {
    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        hints.reflection()
            .registerTypes(
                listOf(
                    TypeReference.of(CurrentTimestampGeneration::class.java),
                    TypeReference.of(PhysicalNamingStrategyStandardImpl::class.java),
                    TypeReference.of(ImplicitNamingStrategyLegacyJpaImpl::class.java)
                )
            ) { builder: TypeHint.Builder ->
                builder.withMembers(
                    *MemberCategory.entries.toTypedArray()
                )
            }
    }
}

Additional Information

Related issue: https://github.com/spring-projects/spring-boot/issues/34737

ilharp avatar May 19 '24 20:05 ilharp