quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Automatic recompilation for Kotlin sources on `quarkusDev` does not work with Quarkus 2.0.0.CR3 (with gradle) #18166

Closed lenalebt closed 3 years ago

lenalebt commented 3 years ago

Describe the bug

When using Kotlin (1.4.32) with Quarkus 2.0.0.CR3 with a gradle build, running ./gradlew quarkusDev builds & starts the application. When making a change to the code and accessing the application again, I expect it to recompile and restart. JVM mode here, of course.

Expected behavior

Recompilation and restart. Works with Quarkus 1.13.7.Final. (you can adjust the version in the reproducer - btw, colors don't work as well with 2.0.0.CR3 in the console in the reproducer, just a side note).

Actual behavior

Recompilation fails with the following http response:

<!doctype html>
<html lang="en">
<head>
    <title>Error restarting Quarkus - java.lang.IllegalArgumentException</title>
    <meta charset="utf-8">
    <style>
html, body {
    margin: 0;
    padding: 0;
    font-family: 'Open Sans', Helvetica, Arial, sans-serif;
    font-size: 100%;
    font-weight: 100;
    line-height: 1.4;
}

html {
    overflow-y: scroll;
}

body {
    background: #f9f9f9;
}
.container {
    width: 80%;
    margin: 0 auto;
}
.content {
    padding: 1em 0 1em 0;
}

header, .component-name {
    background-color: #ad1c1c;
}

ul {
    line-height: 1.5rem;
    margin: 0.25em 0 0.25em 0;
}

.exception-message {
    background: #be2828;
}

h1, h2 {
    margin: 0;
    padding: 0;
}

h1 {
    font-size: 2rem;
    color: #fff;
    line-height: 3.75rem;
    font-weight: 700;
    padding: 0.4rem 0rem 0.4rem 0rem;
}

h2 {
    font-size: 1.2rem;
    color: rgba(255, 255, 255, 0.85);
    line-height: 2.5rem;
    font-weight: 400;
    padding: 0.4rem 0rem 0.4rem 0rem;
}

.intro {    font-size: 1.2rem;
    font-weight: 400;
    margin: 0.25em 0 1em 0;
}
h3 {
    font-size: 1.2rem;
    line-height: 2.5rem;
    font-weight: 400;
    color: #555;
    margin: 0.25em 0 0.25em 0;
}

.trace, .resources {
    background: #fff;
    padding: 15px;
    margin: 15px auto;
    border: 1px solid #ececec;
}
.trace {
    overflow-y: scroll;
}
.hidden {
   display: none;
}

pre {
    white-space: pre;
    font-family: Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace;
    font-size: 12px;
    line-height: 1.5;
    color: #555;
}
</style>
<script>
        function toggleStackTraceOrder() {
                var stElement = document.getElementById('stacktrace');
                var current = stElement.getAttribute('data-current-setting');
                if (current == 'original-stacktrace') {
                        var reverseOrder = document.getElementById('reversed-stacktrace');
                        stElement.innerHTML = reverseOrder.innerHTML;
                        stElement.setAttribute('data-current-setting', 'reversed-stacktrace');
                } else {
                        var originalOrder = document.getElementById('original-stacktrace');
                        stElement.innerHTML = originalOrder.innerHTML;
                        stElement.setAttribute('data-current-setting', 'original-stacktrace');
                }
                return;
        }
        function showDefaultStackTraceOrder() {
                var reverseOrder = document.getElementById('reversed-stacktrace');
                var stElement = document.getElementById('stacktrace');
       if (reverseOrder == null || stElement == null) {
           return;
       }
                // default to reverse ordered stacktrace
                stElement.innerHTML = reverseOrder.innerHTML;
                stElement.setAttribute('data-current-setting', 'reversed-stacktrace');
                return;
        }
</script>
</head>
<body  onload="showDefaultStackTraceOrder()">
<header>
    <h1 class="container">Error restarting Quarkus</h1>
    <div class="exception-message">
        <h2 class="container">java.lang.IllegalArgumentException: Invalid argument: -parameters</h2>
    </div>
</header>
<div class="container content">
    <div id="original-stacktrace" class="trace hidden">
<p><em><a href="" onClick="toggleStackTraceOrder(); return false;">Click Here</a> to see the stacktrace in reversed  order (root-cause first)</em></p>        <pre>java.lang.IllegalArgumentException: Invalid argument: -parameters
        at org.jetbrains.kotlin.cli.common.CLITool.parseArguments(CLITool.kt:121)
        at io.quarkus.kotlin.deployment.KotlinCompilationProvider.compile(KotlinCompilationProvider.java:79)
        at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:191)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:584)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:371)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:350)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$2.handle(VertxHttpHotReplacementSetup.java:64)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$2.handle(VertxHttpHotReplacementSetup.java:54)
        at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:160)
        at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
        at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:158)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2442)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1476)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)</pre>
    </div>
    <div id="reversed-stacktrace" class="trace hidden">
<p><em>The stacktrace below has been reversed to show the root cause first. <a href="" onClick="toggleStackTraceOrder(); return false;">Click Here</a> to see the original stacktrace</eg.IllegalArgumentException: Invalid argument: -parameters
        at org.jetbrains.kotlin.cli.common.CLITool.parseArguments(CLITool.kt:121)
        at io.quarkus.kotlin.deployment.KotlinCompilationProvider.compile(KotlinCompilationProvider.java:79)
        at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:191)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:584)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:371)
        at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:350)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$2.handle(VertxHttpHotReplacementSetup.java:64)
        at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$2.handle(VertxHttpHotReplacementSetup.java:54)
        at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:160)
        at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:96)
        at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:158)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2442)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1476)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)</pre>
    </div>
<div id="stacktrace"></div></div></body>
</html>

To Reproduce

I created a reproducer by just converting the reproducer for #18033 to Kotlin: https://github.com/lenalebt/quarkus-ticket-18033-reproducer/tree/kotlin

Sorry, I don't know if this is gradle-specific at all.

  1. Start the compose stack with docker-compose up in the root directory of the reproducer
  2. Run ./gradlew quarkusDev in the application root.
  3. Access the application by curl http://localhost:8080/hello-resteasy
  4. Make a change to e.g. GreetingResource.kt (for example, add .take(1) in line 20 at the end of the line)
  5. Access the application by curl http://localhost:8080/hello-resteasy - it fails compilation.

I can easily kill the run and restart, then it works. It's just very annoying :-/.

Environment:

Output of uname -a or ver

Linux lena-pc 5.11.0-18-generic #19-Ubuntu SMP Fri May 7 14:22:03 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "11.0.10" 2021-01-19 OpenJDK Runtime Environment GraalVM CE 21.0.0.2 (build 11.0.10+8-jvmci-21.0-b06) OpenJDK 64-Bit Server VM GraalVM CE 21.0.0.2 (build 11.0.10+8-jvmci-21.0-b06, mixed mode, sharing)

Quarkus version or git rev

2.0.0-CR3

Build tool (ie. output of mvnw --version or gradlew --version)


Gradle 7.0

Build time: 2021-04-09 22:27:31 UTC Revision: d5661e3f0e07a8caff705f1badf79fb5df8022c4

Kotlin: 1.4.31 Groovy: 3.0.7 Ant: Apache Ant(TM) version 1.10.9 compiled on September 27 2020 JVM: 11.0.10 (GraalVM Community 11.0.10+8-jvmci-21.0-b06) OS: Linux 5.11.0-18-generic amd64

Additional context

(Add any other context about the problem here.)

quarkus-bot[bot] commented 3 years ago

/cc @evanchooly, @glefloch, @quarkusio/devtools

geoand commented 3 years ago

Can you please trying using 2.0.0.Final?

glefloch commented 3 years ago

I tested it with 999-SNAPSHOT and I can reproduce the issue. If I comment : https://github.com/lenalebt/quarkus-ticket-18033-reproducer/blob/5cfef8c9a1b199973d7ecf0d13ba69eed8077975/build.gradle.kts#L60

It works. I thinks this argument is not a valid compiler args.

gsmet commented 3 years ago

Well, it is for Java. Maybe the problem is that we pass it to Kotlin directly and we shouldn't?

Given the initial build works, I think there's something fishy with what we do in dev mode.

glefloch commented 3 years ago

Yes, I don't think we differentiate compiler arguments, all arguments are put together and set in the devmode context. should we introduce a separate list of argument depending on the compiler ?

lenalebt commented 3 years ago

So, I also do have that problem in another project that does not set this parameter. I can't share the whole thing publicly, sadly, and am unsure where it comes from exactly. I think I'd need more time to boil it down to the exact thing, but it feels a bit shady. The parameter that is problematic for me in the other project is -proc:none:

   <p><em>The stacktrace below has been reversed to show the root cause first. <a href="" onClick="toggleStackTraceOrder(); return false;">Click Here</a> to see the original stacktrace</em></p>        <pre>java.lang.IllegalArgumentException: Invalid argument: 

I'm not really knowingly playing around with compiler options there. But the param seems also to be one that should be passed to a java compiler, not kotlin.

lenalebt commented 3 years ago

Can you please trying using 2.0.0.Final?

Does not make any difference.

lenalebt commented 3 years ago

Soo, this issue really is quite annoying. I can workaround, but it basically removes one of the most interesting features of the whole stack - the "write code"-"rerun request"-cycle. I always need to manually recompile now, and this is one of the things why I left other ecosystems. It also does not support the "continuous testing"-features anymore this way.

I retried on 2.1.3.Final and it still is an issue.

Any chance to get this fixed? I know Kotlin support is experimental, as well as gradle support, but still it would be really nice to get things going over here, as it worked in the past. I sadly don't have any clue where to look for this, otherwise I'd try whether I can make a fix somewhere :).

glefloch commented 3 years ago

@lenalebt have you tried to comment this line/block (https://github.com/lenalebt/quarkus-ticket-18033-reproducer/blob/kotlin/build.gradle.kts#L60) ? This is a configuration for the java compiler which interfere with the quarkus kotlin compiler configuration. As you don't have java main sources, this shouldn't be needed.

lenalebt commented 3 years ago

Well, that's interesting. That makes that minimal example work.

But I don't have that setting anywhere in all the other projects I'm using internally. It still fails though. I don't set any java compiler settings directly - although I don't know whether one of the other plugins will do that. I'll try to re-cycle through them and see what I can throw out :thinking:

glefloch commented 3 years ago

Can you create a reproducer?

gsmet commented 3 years ago

@glefloch how can a setting totally unrelated to Kotlin (and a setting we recommend btw) interfere with the Kotlin compiler?

glefloch commented 3 years ago

@gsmet when building the DevModeLauncher we can set compiler arguments. By default we only look for java compiler argument set in gradle (there is a way to overload those argument in the quarkusDev task). I think we could try to look for kotlin compiler argument as well (if the plugin is applied) but in a multi-source project, there could be issue as there in no way to configure different argument for different compiler in devmode.

lenalebt commented 3 years ago

Okay, I think I now know where it's coming from: I'm using kotlin annotation processing (kapt), and that seems to set compiler arguments for the java compiler. In my case, it's -proc:none. However, I will not be able to get rid of that annotation processing, as we're generating quite a lot of basic code with that.

I don't know exactly where it's coming from in kapt, but this is some things I could find: https://github.com/JetBrains/kotlin/blob/92d200e093c693b3c06e53a39e0b0973b84c7ec5/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/JavacWrapper.kt#L108

This describes very roughly how it seems to work: https://github.com/facebook/buck/issues/956#issuecomment-309080611

It may be different now, that was for an older kotlin version, but it seems like being something from over there.

EDIT: Found a link to kapt source performing this thing: https://github.com/JetBrains/kotlin/blob/06903f803bb9ef9c2f8f625e428e8dcedf4cd3f9/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt#L360-L373

lenalebt commented 3 years ago

I updated the reproducer. It shows exactly the issue that I do have in my private repositories, see https://github.com/lenalebt/quarkus-ticket-18033-reproducer/tree/kotlin and follow instructions in https://github.com/quarkusio/quarkus/issues/18166#issue-930130459 "To Reproduce".

glefloch commented 3 years ago

Thanks @lenalebt I will have a look

Foobartender commented 3 years ago

Now it fails with this stacktrace:

java.lang.RuntimeException: Unable to invoke Kotlin compiler. java.lang.NoSuchMethodError: 'org.picocontainer.ComponentAdapter org.picocontainer.MutablePicoContainer.registerComponentImplementation(java.lang.Object, java.lang.Class)'
    at com.intellij.mock.MockApplication.doGetService(MockApplication.java:66)
    at com.intellij.mock.MockApplication.getService(MockApplication.java:53)
    at com.intellij.psi.LanguageSubstitutors.getInstance(LanguageSubstitutors.java:41)
    at com.intellij.psi.LanguageSubstitutors.<clinit>(LanguageSubstitutors.java:33)
    at com.intellij.lang.LanguageUtil.getLanguageForPsi(LanguageUtil.java:35)
    at com.intellij.psi.impl.file.impl.FileManagerImpl.createFileViewProvider(FileManagerImpl.java:247)
    at com.intellij.psi.impl.file.impl.FileManagerImpl.findViewProvider(FileManagerImpl.java:193)
    at com.intellij.psi.impl.file.impl.FileManagerImpl.findFile(FileManagerImpl.java:357)
    at com.intellij.psi.impl.PsiManagerImpl.findFile(PsiManagerImpl.java:153)
    at org.jetbrains.kotlin.cli.jvm.compiler.CoreEnvironmentUtilsKt.createSourceFilesFromSourceRoots(coreEnvironmentUtils.kt:70)
    at org.jetbrains.kotlin.cli.jvm.compiler.CoreEnvironmentUtilsKt.createSourceFilesFromSourceRoots$default(coreEnvironmentUtils.kt:30)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.createKtFiles(KotlinCoreEnvironment.kt:413)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:187)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:431)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.createCoreEnvironment(K2JVMCompiler.kt:226)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:152)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:90)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
    at io.quarkus.kotlin.deployment.KotlinCompilationProvider.compile(KotlinCompilationProvider.java:82)
    at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:191)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:675)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:420)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:399)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:151)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:139)
    at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
    at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
    at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

    at io.quarkus.kotlin.deployment.KotlinCompilationProvider.compile(KotlinCompilationProvider.java:88)
    at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:191)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:675)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:420)
    at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:399)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:151)
    at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:139)
    at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
    at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
    at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)