micronaut-projects / micronaut-spring

A collection of utilities for Spring users of Micronaut
Apache License 2.0
165 stars 46 forks source link

Micronaut with H2 DB does not work with GraalVM #65

Closed kapitanz closed 8 months ago

kapitanz commented 4 years ago

Steps to Reproduce

1. Create project: mn create-app micronaut-jpa-graal --features data-hibernate-jpa graal-native-image --build maven 2. Add simple classes Job - pojo, entity, service and controller: 1) Data public class Job { @Id @GeneratedValue private Long id; private String name; private Date creationDate; } //getter setter, c-tor 2) Entity: @Repository public interface JobRepository extends CrudRepository<Job, Long> { List findAll(); } 3) Service: @Singleton public class JobService { @Inject JobRepository jobRepository; public List getAllJobs() { return jobRepository.findAll(); } } 4)Controller: @Controller public class JobController { private final JobService jobService; public JobController(JobService jobService) { this.jobService = jobService; } @Get(value = "/jobs", produces = MediaType.APPLICATION_JSON) HttpResponse<List> getJobs() { return HttpResponse.ok(jobService.getAllJobs()); }

3. mvn clean install 4. create script in parent directory, and run that: cd micronaut-jpa-graal sudo docker build -f Dockerfile -t micronaut-jpa-graal . sudo docker run -it -p 8080:8080 micronaut-jpa-graal

  1. TODO

Expected Behaviour

With app created for JVM with $ mn create-app micronaut-jpa-graal --features data-hibernate-jpa --build maven command I was able to start that project without any exceptions and I made successfully some get request on localhost:8080

Actual Behaviour

At the begining Ive run an empty app with simple controller only and result was fine. Then Ive added to project Entity, POJO... to test project with JPA (I have similar app for jvm purposes and it works fine) During app startup I can observe some warnings in terminal:

09:50:45.125 [main] INFO o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.0.Final} Jun 05, 2020 9:50:45 AM org.apache.tomcat.jdbc.pool.ConnectionPool init SEVERE: Unable to create initial connections of pool. org.h2.jdbc.JdbcSQLSyntaxErrorException: (Message 90086 not found) [90086-199] at org.h2.util.JdbcUtils.loadUserClass(JdbcUtils.java:198) at org.h2.engine.Database.getTableEngine(Database.java:3172) at org.h2.schema.Schema.createTable(Schema.java:706) at org.h2.engine.Database.open(Database.java:824) at org.h2.engine.Database.openDatabase(Database.java:319) at org.h2.engine.Database.(Database.java:313) at org.h2.engine.Engine.openSession(Engine.java:69) at org.h2.engine.Engine.openSession(Engine.java:201) at org.h2.engine.Engine.createSessionAndValidate(Engine.java:178) at org.h2.engine.Engine.createSession(Engine.java:161) at org.h2.engine.Engine.createSession(Engine.java:31) at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:336) at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:169) at org.h2.jdbc.JdbcConnection.(JdbcConnection.java:148) at org.h2.Driver.connect(Driver.java:69) at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:319) at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212) at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:744) at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:676) at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:483) at org.apache.tomcat.jdbc.pool.ConnectionPool.(ConnectionPool.java:154) at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101) at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152) at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:175) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:118) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:473) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:84) at org.hibernate.boot.MetadataSources.buildMetadata(MetadataSources.java:185) at io.micronaut.configuration.hibernate.jpa.EntityManagerFactoryBean.hibernateSessionFactoryBuilder(EntityManagerFactoryBean.java:146) at io.micronaut.configuration.hibernate.jpa.$EntityManagerFactoryBean$HibernateSessionFactoryBuilder2Definition.build(Unknown Source) at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:125) at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1714) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2428) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2414) at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2105) at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2079) at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1093) at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1007) at io.micronaut.configuration.hibernate.jpa.$EntityManagerFactoryBean$HibernateSessionFactory3Definition.build(Unknown Source) at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:125) at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1714) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2428) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2414) at io.micronaut.context.DefaultBeanContext.loadContextScopeBean(DefaultBeanContext.java:2004) at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1378) at io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:236) at io.micronaut.context.DefaultBeanContext.readAllBeanDefinitionClasses(DefaultBeanContext.java:2568) at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:202) at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:188) at io.micronaut.runtime.Micronaut.start(Micronaut.java:64) at io.micronaut.runtime.Micronaut.run(Micronaut.java:294) at io.micronaut.runtime.Micronaut.run(Micronaut.java:280) at micronaut.jpa.graal.Application.main(Application.java:17) Caused by: java.lang.ClassNotFoundException: org.h2.mvstore.db.MVTableEngine at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60) at java.lang.Class.forName(DynamicHub.java:1211) at org.h2.util.JdbcUtils.loadUserClass(JdbcUtils.java:191) ... 66 more

09:50:45.129 [main] WARN o.h.e.j.e.i.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : (Message 90086 not found) [90086-199]

When I am trying to perform some Get requests with Talented API Tester I can observe error
"message": "Internal Server Error: Failed to inject value for parameter [sessionFactory] of class: io.micronaut.transaction.hibernate5.HibernateTransactionManager\n\nMessage: No bean of type [org.hibernate.SessionFactory] exists for the given qualifier: @Named('default'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).\nPath Taken: new HibernateTransactionManager([SessionFactory sessionFactory],DataSource dataSource,Interceptor entityInterceptor)"

In terminal I can observe: 10:04:37.121 [pool-3-thread-17] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Failed to inject value for parameter [sessionFactory] of class: io.micronaut.transaction.hibernate5.HibernateTransactionManager

Message: No bean of type [org.hibernate.SessionFactory] exists for the given qualifier: @Named('default'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor). Path Taken: new HibernateTransactionManager([SessionFactory sessionFactory],DataSource dataSource,Interceptor entityInterceptor) io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for parameter [sessionFactory] of class: io.micronaut.transaction.hibernate5.HibernateTransactionManager

Message: No bean of type [org.hibernate.SessionFactory] exists for the given qualifier: @Named('default'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor). Path Taken: new HibernateTransactionManager([SessionFactory sessionFactory],DataSource dataSource,Interceptor entityInterceptor) at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1016) at io.micronaut.transaction.hibernate5.$HibernateTransactionManagerDefinition.doBuild(Unknown Source) at io.micronaut.context.AbstractParametrizedBeanDefinition.build(AbstractParametrizedBeanDefinition.java:117) at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:121) at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1714) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2428) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2414) at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2105) at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2079) at io.micronaut.context.DefaultBeanContext.findBean(DefaultBeanContext.java:1113) at io.micronaut.context.DefaultBeanContext.findBean(DefaultBeanContext.java:626) at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:114) at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1714) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2428) at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2414) at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2105) at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2079) at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:621) at io.micronaut.data.intercept.DataIntroductionAdvice.findInterceptor(DataIntroductionAdvice.java:121) at io.micronaut.data.intercept.DataIntroductionAdvice.intercept(DataIntroductionAdvice.java:78) at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:69) at io.micronaut.validation.ValidatingInterceptor.intercept(ValidatingInterceptor.java:123) at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:69) at micronaut.jpa.graal.jobs.JobRepository$Intercepted.findAll(Unknown Source) at micronaut.jpa.graal.jobs.JobService.getAllJobs(JobService.java:14) at micronaut.jpa.graal.jobs.JobController.getJobs(JobController.java:24) at micronaut.jpa.graal.jobs.$JobControllerDefinition$$exec1.invokeInternal(Unknown Source) at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:146) at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:3016) at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:228) at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122) at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$16(RoutingInBoundHandler.java:1460) at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71) at io.reactivex.Flowable.subscribe(Flowable.java:14918) at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37) at io.reactivex.Flowable.subscribe(Flowable.java:14918) at io.reactivex.internal.operators.flowable.FlowableSwitchIfEmpty.subscribeActual(FlowableSwitchIfEmpty.java:32) at io.reactivex.Flowable.subscribe(Flowable.java:14918) at io.reactivex.Flowable.subscribe(Flowable.java:14868) at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:52) at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:68) at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52) at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29) at io.reactivex.Flowable.subscribe(Flowable.java:14918) at io.reactivex.Flowable.subscribe(Flowable.java:14865) at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82) at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:288) at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run(ExecutorScheduler.java:253) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.lang.Thread.run(Thread.java:834) at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:527) at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193) Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [org.hibernate.SessionFactory] exists for the given qualifier: @Named('default'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor). at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2046) at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1093) at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1007) ... 52 common frames omitted

Environment Information

ilopmar commented 4 years ago

Make sure that you have configured properly GraalVM for H2. We have a test application for Micronaut 1.3.x here https://github.com/micronaut-graal-tests/micronaut-data-jpa-graal/tree/1.3.x_h2

That application is using snapshot versions of Micronaut and Micronaut Data that include a lot of improvements for GraalVM support, so you may need to add configuration manually to your application. You probably need to apply a "revert" of this commit https://github.com/micronaut-graal-tests/micronaut-data-jpa-graal/commit/041b81fc8eb08e84a61abb99370cfe47ff1f5272 to your app. And maybe also this (not 100% sure): https://github.com/micronaut-graal-tests/micronaut-data-jpa-graal/commit/7d7525304dbebadb29910bcaa3af3e87b28df7c8

kapitanz commented 4 years ago

OK, thank you for quick response, I will try with your example.

kapitanz commented 4 years ago

Hi @ilopmar Ive tried to customize my maven app to make it similar to your test application, but I have still the same issues. As a matter of fact I dont understand why you dockerfile is completelly different than docker file created out of the box with Micronaut graal vm project. Here https://github.com/micronaut-graal-tests/micronaut-data-jpa-graal/blob/1.3.x_h2/Dockerfile we can see creation of the typical Java container and run app as a .jar instead of graalvm like this: FROM oracle/graalvm-ce:20.0.0-java11 as graalvm RUN gu install native-image

Could you please confirm whether Micronaut with GraalVm are compatible with embedded H2 DB or maybe remote DB?

ilopmar commented 4 years ago

My Dockerfile is different because it is for a normal JVM app and because I don't use Docker in that project. I should remove it.

Yes, I confirm that Micronaut and GraalVM are compatible with an embedded H2 DB. I've never tried with a remote H2 DB.

This is the latest execution of the CI pipeline app for Micronaut Data JPA with H2: