quarkus: Gradle + Kotlin: failure to run or build

I’ve tried setting up a minimal project with Gradle (5.2.1) and Kotlin (1.3.21) and of course Quarkus (0.11.0), but it failed with many issues.

The complete project is available at https://github.com/jnizet/quarkustest

Here are the various issues I faced during this experiment.

First, the guide about Gradle promotes quite discouraged practices, like applying plugins imperatively rather than using the plugins block, which is necessary to benefit from the generated type-safe extensions when using the Gradle Kotlin DSL. Or using deprecated configurations, like testCompile. I know how to fix that, so it’s not a big issue for me, but the Gradle guide could be improved.

The Kotlin guide doesn’t explain how to use configure a Kotlin Quarkus project with Gradle. So I had to make guesses based on the Maven instructions and on the source code of the gradle plugin. This could be improved too. I don’t have numbers, but Kotlin developers probably use Gradle more than Maven, so having a guide showing the usage of both together would be nice. In particular, one thing that is not obvious is how to do the equivalent of the following:

Maven’s sourceDirectory and testSourceDirectory build properties are configured to point to Kotlin sources (src/main/kotlin and src/test/kotlin respectively)

Executing ./gradlew tasks to know what the gradle plugin does gives the following:

Quarkus tasks
-------------
add-extension - Adds one of the available quarkus extensions to the current project
list-extensions - Lists the available quarkus extensions
quarkus-build - Quarkus builds a runner jar based on the build jar
quarkus-dev - Creates a native image
quarkus-native - Building a native image

The descriptions don’t seem correct and clear to me, especially the one of quarkus-dev task. Two other things that look weird to me is that the standard Gradle lifecycle and conventions don’t seem to be respected:

  • ./gradlew assemble should build the final runnable jar file
  • the generated jar file should be under build/libs, not build/lib

If the Quarkus plugin is applied, but the quarkus gradle extension is not configured, running ./gradlew quarkus-dev gives the following:

Execution failed for task ':quarkus-dev'.
> The `src/main/java` directory is required, please create it.

That’s weird: I shouldn’t have to create such a directory if using Kotlin only. And BTW, creating the src/main/java directory has absolutely no effect: the same error message is still generated if I do.

So I thought this must have to do with the sourceDirectory, that is changed to src/main/kotlin in the Maven instructions. Reading the Gradle plugin source code, my guess was that I had to add this to the gradle build script:

quarkus {
    setSourceDir("src/main/kotlin")
}

That makes the quarkus-dev task work (sort of): it doesn’t throw any error, and gives the same output as when using Java. But navigating to http://localhost:8080/ then gives the following error message:

java.lang.RuntimeException: Unable to invoke Kotlin compiler
	at io.quarkus.kotlin.deployment.KotlinCompilationProvider.compile(KotlinCompilationProvider.java:41)
	at io.quarkus.dev.ClassLoaderCompiler.compile(ClassLoaderCompiler.java:135)
	at io.quarkus.dev.RuntimeUpdatesProcessor.scanForChangedClasses(RuntimeUpdatesProcessor.java:111)
	at io.quarkus.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:83)
	at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup.handleHotDeploymentRequest(UndertowHotReplacementSetup.java:54)
	at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup$1$1.handleRequest(UndertowHotReplacementSetup.java:35)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1998)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1525)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1416)
	at java.lang.Thread.run(Thread.java:748)

I have no idea how to fix that issue. So I tried to execute the quarkus-build task (after a clean), and it gave the following exception:

io.quarkus.creator.AppCreatorException: Failed to build a runner jar
        at io.quarkus.creator.phase.runnerjar.RunnerJarPhase.provideOutcome(RunnerJarPhase.java:199)
        at io.quarkus.creator.phase.runnerjar.RunnerJarPhase.provideOutcome(RunnerJarPhase.java:70)
        at io.quarkus.creator.outcome.OutcomeResolver.resolve(OutcomeResolver.java:48)
        at io.quarkus.creator.AppCreator.resolveOutcome(AppCreator.java:255)
        at io.quarkus.gradle.tasks.QuarkusBuild.buildQuarkus(QuarkusBuild.java:172)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:103)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:705)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:672)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$4.run(ExecuteActionsTaskExecuter.java:338)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:327)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:312)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:75)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:158)
        at org.gradle.internal.execution.impl.steps.ExecuteStep.execute(ExecuteStep.java:46)
        at org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute(CancelExecutionStep.java:34)
        at org.gradle.internal.execution.impl.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:69)
        at org.gradle.internal.execution.impl.steps.TimeoutStep.execute(TimeoutStep.java:49)
        at org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
        at org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute(CreateOutputsStep.java:49)
        at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:42)
        at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:28)
        at org.gradle.internal.execution.impl.steps.CacheStep.executeWithoutCache(CacheStep.java:133)
        at org.gradle.internal.execution.impl.steps.CacheStep.lambda$execute$5(CacheStep.java:83)
        at java.util.Optional.orElseGet(Optional.java:267)
        at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:82)
        at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:37)
        at org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute(PrepareCachingStep.java:33)
        at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:38)
        at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:23)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:95)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:88)
        at java.util.Optional.map(Optional.java:215)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:34)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:109)
        at org.gradle.api.internal.tasks.execution.ResolveIncrementalChangesTaskExecuter.execute(ResolveIncrementalChangesTaskExecuter.java:84)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter.execute(ResolveBeforeExecutionStateTaskExecuter.java:74)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:109)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:93)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:45)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:63)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:46)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.lang.Thread.run(Thread.java:748)
Caused by: io.quarkus.creator.AppCreatorException: Failed to augment application classes
        at io.quarkus.creator.phase.augment.AugmentPhase.doProcess(AugmentPhase.java:398)
        at io.quarkus.creator.phase.augment.AugmentPhase.provideOutcome(AugmentPhase.java:196)
        at io.quarkus.creator.phase.augment.AugmentPhase.provideOutcome(AugmentPhase.java:82)
        at io.quarkus.creator.outcome.OutcomeResolver.resolve(OutcomeResolver.java:48)
        at io.quarkus.creator.AppCreator.resolveOutcome(AppCreator.java:255)
        at io.quarkus.creator.phase.runnerjar.RunnerJarPhase.provideOutcome(RunnerJarPhase.java:197)
        ... 89 more
Caused by: org.jboss.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.deployment.steps.SubstrateSystemPropertiesBuildStep#writeNativeProps threw an exception: java.lang.IllegalStateException: java.io.FileNotFoundException: /Users/jb/projects/quarkustest/build/classes/java/main:/Users/jb/projects/quarkustest/build/classes/kotlin/main/native-image.properties (No such file or directory)
        at org.jboss.builder.Execution.run(Execution.java:123)
        at org.jboss.builder.BuildExecutionBuilder.execute(BuildExecutionBuilder.java:136)
        at io.quarkus.deployment.QuarkusAugmentor.run(QuarkusAugmentor.java:102)
        at io.quarkus.creator.phase.augment.AugmentPhase.doProcess(AugmentPhase.java:316)
        ... 94 more
Caused by: java.lang.IllegalStateException: java.io.FileNotFoundException: /Users/jb/projects/quarkustest/build/classes/java/main:/Users/jb/projects/quarkustest/build/classes/kotlin/main/native-image.properties (No such file or directory)
        at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:444)
        at org.jboss.builder.BuildContext.run(BuildContext.java:413)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1998)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1525)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1416)
        at java.lang.Thread.run(Thread.java:748)
        at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.io.FileNotFoundException: /Users/jb/projects/quarkustest/build/classes/java/main:/Users/jb/projects/quarkustest/build/classes/kotlin/main/native-image.properties (No such file or directory)
        at java.io.FileOutputStream.open0(Native Method)
        at java.io.FileOutputStream.open(FileOutputStream.java:270)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
        at io.quarkus.deployment.steps.SubstrateSystemPropertiesBuildStep.writeNativeProps(SubstrateSystemPropertiesBuildStep.java:45)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:435)
        ... 7 more

At that point, I’m stuck.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 6
  • Comments: 83 (56 by maintainers)

Most upvoted comments

@stalep suggestion: you guys might want to have a label for issues related to kotlin.

Gradle support has received a lot of fixes in the latest release, I suggest you give 0.18.0 a try 😃

@renannprado I managed to attach the debugger to the process using

tasks {
    "quarkusDev"(QuarkusDev::class) {
        debug = "true"
    }
}

I set it to break at any exception and I immediately got a NoSuchFileException

grafik

I think the reason are these two lines:

-Dquarkus-internal.runner.classes=C:\Users\Kirill\.gradle\daemon\5.2.1\build\classes\kotlin\main
-Dquarkus-internal.runner.sources=C:\Users\Kirill\.gradle\daemon\5.2.1\src\main\kotlin

The directories are incorrectly resolved.

In the build.gradle.kts I changed the configuration to

quarkus {
    setSourceDir(project.projectDir.resolve("src/main/kotlin").absolutePath)
    setOutputDirectory(project.buildDir.resolve("classes/kotlin/main").absolutePath)
}

Now the exception went away, but the server still doesn’t run properly. Same output as before.

@renannprado @geoand FYI Gradle QuickStart (with Java, not Kotlin) in https://github.com/quarkusio/quarkus-quickstarts/issues/75

I was able to get this work by adding the following dependencies:

implementation("org.jetbrains.intellij.deps:trove4j:1.0.20181211")
implementation("org.jetbrains.kotlin:kotlin-script-runtime:1.3.21")

It seems like for some reason the process that creates the devjar does not resolve the correct dependencies (for the Kotlin compiler) when launched via the Gradle plugin - cc @aloubyansky.

The fact that there is work actively being done for bootstrapping makes me reluctant to dig into this more. It’s probably best that we reexamine this once that works lands.

I’ve submitted the PR https://github.com/quarkusio/quarkusio.github.io/pull/135 to improve the Gradle guide.

Thanks for your investigations @MartinX3 I did upgrade my example repo to 1.0.1.Final

That command was just to create a new project that is properly configured so you can compare.

Thank you.

That’s less « hacky » than what I mentioned earlier in the thread indeed.

👍

I was editing my comment when you posted. Sorry, it seems to work with 0.18.0 I’ll submit a PR to @renannprado 's repository.

Thank you for your work to support Gradle + kotlin.

Verified on my machine as well 😃

I tested this locally against master and the test @renannprado provided now works (I also asked @geoand to verify 😃.

@renannprado No, it will only fix the Error opening zip stream from artifact error, everything else we have discussed still applies (I updated my comment to make that more clear)

@renannprado Yeah, I got the same error as well and to be honest I though it was a corrupted cache on my machine - obviously with this happening to you as well that’s not the case. But at least that error happens much further down in the process. I am not sure what the problem is but I’ll look into it soon I hope.

@renannprado I do not unfortunately, I haven’t had time to look into that yet, but hopefully I will soon enough.

@geoand A complete project reproducing the issue is available at https://github.com/jnizet/quarkustest