micronaut-projects / micronaut-data

Ahead of Time Data Repositories
Apache License 2.0
465 stars 197 forks source link

Unable to build using GraalVM native-image tool #166

Closed ivangfr closed 5 years ago

ivangfr commented 5 years ago

Hi, I am trying to use GraalVM native-image tool to build a simple Micronaut application, but I am getting an exception.

The application is a simple book-api and its source-code is: https://github.com/ivangfr/graalvm-micronaut-springboot-comparison/tree/master/book-api. You can use it in case you want to replicate the exception.

Below is the exception that I am getting

Error: Classes that should be initialized at run time got initialized during image building:
 org.springframework.jdbc.datasource.ConnectionProxy the class was requested to be initialized at build time (from the command line). com.sun.proxy.$Proxy355 caused initialization of this class with the following trace: 

com.oracle.svm.core.util.UserError$UserException: Classes that should be initialized at run time got initialized during image building:
 org.springframework.jdbc.datasource.ConnectionProxy the class was requested to be initialized at build time (from the command line). com.sun.proxy.$Proxy355 caused initialization of this class with the following trace: 

        at com.oracle.svm.core.util.UserError.abort(UserError.java:65)
        at com.oracle.svm.hosted.classinitialization.ConfigurableClassInitialization.checkDelayedInitialization(ConfigurableClassInitialization.java:494)
        at com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.duringAnalysis(ClassInitializationFeature.java:188)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$8(NativeImageGenerator.java:711)
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:63)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:711)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:526)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:444)
        at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Image build request failed with exit status 1

I am using the following arguments in native-image.properties

Args = -H:IncludeResources=logback.xml|application.yml \
       -H:Name=micronaut-book-api \
       -H:Class=com.mycompany.micronautbookapi.Application \
       -H:+TraceClassInitialization \
       -H:+ReportExceptionStackTraces \
       --initialize-at-run-time=java.sql.DriverManager \
       --initialize-at-run-time=org.springframework.jdbc.datasource.ConnectionProxy

Thanks!

ivangfr commented 5 years ago

@graemerocher

After the changes you did, I am still facing the same problem. I have updated my build.gradle

from

set('micronautVersion', '1.2.2')
set('micronautDataVersion', '1.0.0.M1')

to

set('micronautVersion', '1.2.3')
set('micronautDataVersion', '1.0.0.M2')

Should I do any other changes in my code?

graemerocher commented 5 years ago

Ah I see you are using the JPA impl

The fix only applies to the JDBC impl. As a workaround you can copy this class into your project until I add the equivalent one for JPA:

https://github.com/micronaut-projects/micronaut-data/blob/master/data-jdbc/src/main/java/io/micronaut/data/jdbc/graal/DataSourceTransactionManagerFactorySubstitutions.java

Sorry about that

graemerocher commented 5 years ago

Fixed this for good in master by removing Spring for transaction management

ivangfr commented 5 years ago

Hey @graemerocher

I've updated the build.gradle file of my project https://github.com/ivangfr/graalvm-micronaut-springboot-comparison/tree/master/book-api

from

set('micronautVersion', '1.2.2')
set('micronautDataVersion', '1.0.0.M1')

to

set('micronautVersion', '1.2.3')
set('micronautDataVersion', '1.0.0.M3')

I haven't commit the code, but that is the only change.

And I am getting

[pool-1-thread-4] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Error instantiating bean of type  [io.micronaut.data.hibernate.operations.HibernateJpaOperations]

Message: Missing bean argument value: transactionOperations
Path Taken: new HibernateJpaOperations(SessionFactory sessionFactory,[TransactionOperations transactionOperations],ExecutorService executorService)
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type  [io.micronaut.data.hibernate.operations.HibernateJpaOperations]

Message: Missing bean argument value: transactionOperations
Path Taken: new HibernateJpaOperations(SessionFactory sessionFactory,[TransactionOperations transactionOperations],ExecutorService executorService)
        at io.micronaut.context.AbstractParametrizedBeanDefinition.build(AbstractParametrizedBeanDefinition.java:103)
        at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:109)
        at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1610)
        at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2319)
        at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2001)
        at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:1975)
        at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:622)
        at io.micronaut.data.intercept.DataIntroductionAdvice.findInterceptor(DataIntroductionAdvice.java:105)
        at io.micronaut.data.intercept.DataIntroductionAdvice.intercept(DataIntroductionAdvice.java:76)
        at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:69)
        at com.mycompany.micronautbookapi.repository.BookRepository$Intercepted.findAll(Unknown Source)
        at com.mycompany.micronautbookapi.service.BookServiceImpl.getBooks(BookServiceImpl.java:20)
        at com.mycompany.micronautbookapi.rest.BookController.getBooks(BookController.java:28)
        at com.mycompany.micronautbookapi.rest.$BookControllerDefinition$$exec1.invokeInternal(Unknown Source)
        at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:145)
        at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:2856)
        at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:235)
        at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:122)
        at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$17(RoutingInBoundHandler.java:1401)
        at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71)
        at io.reactivex.Flowable.subscribe(Flowable.java:14918)
        at io.reactivex.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        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.Flowable.subscribe(Flowable.java:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        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:14865)
        at io.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        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:52)
        at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:52)
        at io.micronaut.configuration.metrics.binder.web.WebMetricsPublisher.subscribe(WebMetricsPublisher.java:122)
        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.micronaut.reactive.rxjava2.RxInstrumentedFlowable.subscribeActual(RxInstrumentedFlowable.java:68)
        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 io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:79)
        at io.micrometer.core.instrument.Timer.lambda$wrap$0(Timer.java:144)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

The application is so simple that I didn't add transaction annotation to it.

I've seen some comments on Gitter (https://gitter.im/micronautfw/questions?at=5d9c6a89eac5612d22d68126), but I haven't got exactly what to do. I am following the https://micronaut-projects.github.io/micronaut-data/latest/guide/ Maybe, I am missing still something.

Thanks!

ivangfr commented 5 years ago

One way to solve is to use Spring Data Support

implementation "io.micronaut.data:micronaut-data-spring:1.0.0.M3"
implementation "org.springframework:spring-orm:5.2.0.RELEASE"

Without it, I always have

Message: Missing bean argument value: transactionOperations

However, even using the micronaut-data version 1.0.0.M3, I am still facing the problem while building the native image using GraalVM

Error: Classes that should be initialized at run time got initialized during image building:
 org.springframework.jdbc.datasource.ConnectionProxy the class was requested to be initialized at build time (from the command line). com.sun.proxy.$Proxy355 caused initialization of this class with the following trace: 

com.oracle.svm.core.util.UserError$UserException: Classes that should be initialized at run time got initialized during image building:
 org.springframework.jdbc.datasource.ConnectionProxy the class was requested to be initialized at build time (from the command line). com.sun.proxy.$Proxy355 caused initialization of this class with the following trace: 

        at com.oracle.svm.core.util.UserError.abort(UserError.java:65)
        at com.oracle.svm.hosted.classinitialization.ConfigurableClassInitialization.checkDelayedInitialization(ConfigurableClassInitialization.java:494)
        at com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.duringAnalysis(ClassInitializationFeature.java:188)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$8(NativeImageGenerator.java:711)
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:63)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:711)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:526)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:444)
        at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Image build request failed with exit status 1

@graemerocher should we reopen this issue?

Thanks!

graemerocher commented 5 years ago

Please see https://github.com/micronaut-projects/micronaut-data/tree/master/examples/example-jpa for a working example with the correct dependencies

ivangfr commented 5 years ago

Hey

I've used the example-jpa as a base for fixing my project and it works now.

However, I needed to change many things like, add some Hibernate configuration in build.gradle, replace micronaut-jdbc-hikari with micronaut-jdbc-tomcat and use H2 instead of MySQL. I also needed to disable the micrometer