Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt native support for Hibernate 6.3.0 bytecode provider changes #31051

Closed
sdeleuze opened this issue Aug 15, 2023 · 12 comments
Closed

Adapt native support for Hibernate 6.3.0 bytecode provider changes #31051

sdeleuze opened this issue Aug 15, 2023 · 12 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Milestone

Comments

@sdeleuze
Copy link
Contributor

The native support for Hibernate should be refined in order to be compatible with those changes related to the bytecode provider management expected to be part of the upcoming Hibernate 6.3.0.Final release.

We should also retain compatibility with previous versions down to Hibernate 5.6.x.

We should test such refined Hibernate support using our AOT smoke tests using Hibernate 6.3.0.CR1 (or a more recent version available).

@sdeleuze sdeleuze added in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement theme: aot An issue related to Ahead-of-time processing labels Aug 15, 2023
@sdeleuze sdeleuze added this to the 6.1.0-RC1 milestone Aug 15, 2023
@sdeleuze sdeleuze self-assigned this Aug 15, 2023
@Eng-Fouad
Copy link

Related: #30521 (comment)

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Sep 5, 2023

This fails with Hibernate 6.3.0, as Environment.USE_REFLECTION_OPTIMIZER was removed

@Eng-Fouad I did some related tests and found it seems to not fail in practice due to inlining of the Environment static final fields since Spring Framework is built against a previous version of Hibernate. I re-rested with 6.3.1-SNAPSHOT and it seems to be fine. Do you have a reproducer or were you expecting this to fail "in theory"?

@Eng-Fouad
Copy link

This fails with Hibernate 6.3.0, as Environment.USE_REFLECTION_OPTIMIZER was removed

@Eng-Fouad I did some related tests and found it seems to not fail in practice due to inlining of the Environment static final fields since Spring Framework is built against a previous version of Hibernate. I re-rested with 6.3.1-SNAPSHOT and it seems to be fine. Do you have a reproducer or were you expecting this to fail "in theory"?

Here is a reproducer: https://github.com/Eng-Fouad/spring-boot-native-3.1.3-with-hibernate-6.3.0

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Sep 5, 2023

Thanks for the reproducer, so far Spring Boot 3.1 and related Spring Framework version are not supporting Hibernate 6.3, so that's expected. For next Spring Boot 3.2 milestone or RC, it should work with the changes implemented in #29549 and when using Hibernate 6.3.1-SNAPSHOT (6.3.0.Final is broken for other reasons).

@sdeleuze sdeleuze closed this as completed Sep 5, 2023
@vladimirfx
Copy link

Setting hibernate.bytecode.provider=none leads to a 100% crash at context startup for non-native builds. It obviously a Hibernate bug because the reflection optimizer is obtained unconditionally and none bytecode provider always throws the exception. Unfortunately, I can't file an issue. Does anyone can file an issue?

Stacktrace:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ru.fcb.mobilefieldcollection.backend.internal.content.ContentExtendedTransactionFilter#0': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'transactionTemplate' defined in class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'transactionTemplate' parameter 0: Error creating bean with name 'transactionManager' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:802)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:241)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1193)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:210)
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:173)
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:168)
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:153)
	at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:86)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:266)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:240)
	at org.springframework.boot.web.embedded.jetty.ServletContextInitializerConfiguration.callInitializers(ServletContextInitializerConfiguration.java:65)
	at org.springframework.boot.web.embedded.jetty.ServletContextInitializerConfiguration.configure(ServletContextInitializerConfiguration.java:54)
	at org.eclipse.jetty.ee10.webapp.Configurations.configure(Configurations.java:505)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.configure(WebAppContext.java:477)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.startContext(WebAppContext.java:1219)
	at org.eclipse.jetty.ee10.servlet.ServletContextHandler.lambda$doStart$0(ServletContextHandler.java:1041)
	at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.call(ContextHandler.java:1206)
	at org.eclipse.jetty.ee10.servlet.ServletContextHandler.doStart(ServletContextHandler.java:1038)
	at org.eclipse.jetty.ee10.webapp.WebAppContext.doStart(WebAppContext.java:496)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171)
	at org.eclipse.jetty.server.Server.start(Server.java:622)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:121)
	at org.eclipse.jetty.server.Handler$Abstract.doStart(Handler.java:472)
	at org.eclipse.jetty.server.Server.doStart(Server.java:563)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
	at org.springframework.boot.web.embedded.jetty.JettyWebServer.initialize(JettyWebServer.java:120)
	... 96 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'transactionTemplate' defined in class path resource [org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'transactionTemplate' parameter 0: Error creating bean with name 'transactionManager' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:802)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1166)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1441)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1348)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
	... 129 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1441)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1348)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
	... 143 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1775)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1321)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1282)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
	at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:120)
	at org.springframework.orm.jpa.JpaTransactionManager.setBeanFactory(JpaTransactionManager.java:333)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1796)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1763)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
	... 153 more
Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1822)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1771)
	... 169 more
Caused by: org.hibernate.HibernateException: Using the ReflectionOptimizer is not possible when the configured BytecodeProvider is 'none'. Use a different BytecodeProvider
	at org.hibernate.bytecode.internal.none.BytecodeProviderImpl.getReflectionOptimizer(BytecodeProviderImpl.java:48)
	at org.hibernate.metamodel.internal.EntityRepresentationStrategyPojoStandard.resolveReflectionOptimizer(EntityRepresentationStrategyPojoStandard.java:289)
	at org.hibernate.metamodel.internal.EntityRepresentationStrategyPojoStandard.<init>(EntityRepresentationStrategyPojoStandard.java:160)
	at org.hibernate.metamodel.internal.ManagedTypeRepresentationResolverStandard.resolveStrategy(ManagedTypeRepresentationResolverStandard.java:62)
	at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:518)
	at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:135)
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:92)
	at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:75)
	at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.processBootEntities(MappingMetamodelImpl.java:244)
	at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.finishInitialization(MappingMetamodelImpl.java:182)
	at org.hibernate.internal.SessionFactoryImpl.initializeMappingModel(SessionFactoryImpl.java:323)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:273)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:450)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1507)
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
	... 173 more

@sdeleuze
Copy link
Contributor Author

@vladimirfx What is your use case for setting explicitly hibernate.bytecode.provider=none (should be handled correctly for native out of the box with Spring)?

@vladimirfx
Copy link

@vladimirfx What is your use case for setting explicitly hibernate.bytecode.provider=none (should be handled correctly for native out of the box with Spring)?

We use JVM. Conceptually I against proxies especially when build time weaving already done. We use Kotlin mostly and I won't open my classes. Up to 6.3 all works as expected.

@vladimirfx
Copy link

Spring uses a workaround (native substitution), Quarkus uses a workaround (native substitution + pregenerated proxies). I can't understand why a valid configuration is 100% nonfunctional and no issues are created...
What is wrong with weaving for JVM? One of our projects uses compile-time entities weaving for 12 years first with Eclipselink and then with Hibernate. Maybe I'm not understand something fundamental but I want that my class remain my class at runtime (and NO subclass).

@sdeleuze
Copy link
Contributor Author

I don't challenge the relevancy of your ask, I was just curious of your use case.

I have created the related https://hibernate.atlassian.net/browse/HHH-17568 issue since that should indeed be fixed on Hibernate side.

@vladimirfx
Copy link

I don't challenge the relevancy of your ask, I was just curious of your use case.

I have created the related https://hibernate.atlassian.net/browse/HHH-17568 issue since that should indeed be fixed on Hibernate side.

Thank you so much!

@StevenPG
Copy link

StevenPG commented Feb 5, 2024

@sdeleuze Do you have any insights outside of the information on the ticket https://hibernate.atlassian.net/browse/HHH-17568?

We're running into this issue as well.

Also 3.1.3, since 3.2.1 and 3.2.2 seem to be broken for native-image due to spring-projects/spring-security#14362

@sdeleuze
Copy link
Contributor Author

sdeleuze commented Feb 6, 2024

@StevenPG Nope, but this issue is expected to be fixed by the the substitution, and an upcoming fix seems planned for Hibernate 6.4.4 as mentioned in the issue.

The Spring security bug will be fixed in Boot 3.3.3 as mentioned in this comment.

So there should be no issue with Boot + Security latest snapshots. If you see something broken, please create an issue with minimal repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants