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

Kotlin Multiplatform Plugin+ Gradle + QuarkusDev #10987

Open
darren-bell-nanthealth opened this issue Jul 27, 2020 · 10 comments
Open

Kotlin Multiplatform Plugin+ Gradle + QuarkusDev #10987

darren-bell-nanthealth opened this issue Jul 27, 2020 · 10 comments
Labels
area/gradle Gradle area/kotlin kind/bug Something isn't working

Comments

@darren-bell-nanthealth
Copy link

Describe the bug
When I change the kotlin code in Kotlin Multiplatform plugin project, where quarkus is serving the backend, I would expect the quarkusDev gradle task to hot reload/deploy changes

Expected behavior
Changes to the Kotlin code in the quarkus backend source to be compiled and redeployed

Actual behavior
Nothing happens

To Reproduce
Steps to reproduce the behavior:

  1. Clone https://gitlab.com/zsinz-kotlin/kotlin-multiplatform-quarkus
  2. run: gradlew quarkusDev
  3. change source code in src/jvmMain/kotlin/com/zsinz/kotlin/multiplatform/quarkus/Controller.kt
  4. save change

Configuration

# Add your application.properties here, if applicable.

Screenshots
(If applicable, add screenshots to help explain your problem.)

Environment (please complete the following information):

  • Output of uname -a or ver:
    Linux BFSWDBEL 4.19.104-microsoft-standard Switch to the Maven distributed copy of the SubstrateVM annotations #1 SMP Wed Feb 19 06:37:35 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
  • Output of java -version:
    openjdk version "11.0.6" 2020-01-14
    OpenJDK Runtime Environment GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07)
    OpenJDK 64-Bit Server VM GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07, mixed mode, sharing)
  • GraalVM version (if different from Java):
  • Quarkus version or git rev:
    1.6.0.Final
  • Build tool (ie. output of mvnw --version or gradlew --version):

Gradle 6.5.1

Build time: 2020-06-30 06:32:47 UTC
Revision: 66bc713f7169626a7f0134bf452abde51550ea0a

Kotlin: 1.3.72
Groovy: 2.5.11
Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM: 11.0.6 (Oracle Corporation 11.0.6+9-jvmci-19.3-b07)
OS: Linux 4.19.104-microsoft-standard amd64

Additional context
(Add any other context about the problem here.)

@darren-bell-nanthealth darren-bell-nanthealth added the kind/bug Something isn't working label Jul 27, 2020
@quarkusbot
Copy link

/cc @quarkusio/devtools

@ghost
Copy link

ghost commented Jan 24, 2021

There is also no live-reload/hot-replace for Kotlin files in Maven projects.

In a mixed Java + Kotlin Quarkus application: if I change a Java source file then live-reload/hot-replace is performed. However, if I change a Kotlin source file then the change is not detected.

@fercomunello
Copy link
Contributor

fercomunello commented Aug 1, 2022

@belu Exactly. Even after the build and publishToMavenLocal tasks of Gradle been executed, Quarkus dev-mode don't hot reload this changes on the classpath, I tryed to debug "Thread.currentThread().getContextClassLoader()" and I found my Kotlin compiled class, but without the methods that I added before. This behaviour causes a runtime exception on Quarkus hot reload and the only way to solve is by restarting the process, wich is little annoying as I do a lot of changes on my external artifact.

I am using Quarkus 2.11 with JDK 17, my artifact is a Kotlin MPP Library but on the Quarkus project I using Java. It will be very good if the Quarkus hot-reload feature works with that setup.

@aloubyansky
Copy link
Member

@belu @fercomunello your use-case is different than the original issue. Please create a new one to track yours, mention me and if you can attach/reference a reproducer that will help a lot to fix it faster. Thanks!

@fercomunello
Copy link
Contributor

@aloubyansky Done, thanks!

@fercomunello
Copy link
Contributor

fercomunello commented Aug 14, 2022

@belu If you are dealing with Kotlin non multiplatform code, just add this extension:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-kotlin</artifactId>
</dependency>

@fercomunello
Copy link
Contributor

fercomunello commented Aug 15, 2022

You may be thinking that the solution for live-reload in dev mode between a Kotlin Multiplatform Library and Quarkus project is to just use Gradle modules, as multiplatform plugin exists only for Gradle, right? But it will not work, because the quarkus-kotlin extension is only able to compile for JVM environments, it is not a multiplatform compilant extension and is not propused to be one.

A quick explanation about Kotlin Multiplatform
Multiplatform compilation is based on expect and actual pattern, it's used when common module doesn't has a platform specific implementation built-in on the standard library, so it will expects to a specific platform module implementation, then the common code dynamically calls the right implementation during runtime. A great example is java.math.BigDecimal class, it's a JVM specific implementation that doesn't built-in on the kotlin-stdlib, this class is only acessible by jvmMain module, so let's say that my common module needs to perform monetary operations, for that I can create a expect common class like commonMain/MonetaryAmount.kt and 2 actual implementations, one actual class for JVM that will use java.math.BigDecimal and another actual class for iOS that will use swift.NSDecimalNumber to execute the operations like add, multiply, subtract, divide and so on ...

A quick explanation about how Quarkus live compilation works
The Quarkus Core module has the CompilationProvider interface that is implemented by JavaCompilationProvider class, this custom compiler is built-in on every Quarkus project because it's essencial of course. But, for projects that uses Kotlin or have to mix Java and Kotlin between Maven or Gradle modules, it's necessary to add the quarkus-kotin extension, because this extension provides a KotlinCompilationProvider class that uses K2JVMCompiler internally, this compilation provider is registered by Quarkus using a ServiceLoader. Live reload works as expected in this case, even if the Quarkus application is a Java project and the shared library is written in Kotlin, or vice-versa.

A fix for this can be tricky:
Quarkus Kotlin extension needs to somehow detects the Gradle modules (common, jvm) via a kotlin multiplatform plugin integration and then trigger multiplatform compilation before compile the application code.

@fercomunello
Copy link
Contributor

@darren-bell-nanthealth This issue has been open for a long time and I don't know if it would make sense to mix multiplatform code with Quarkus, look at Ktor framework if you want to only use Kotlin features. Or, what makes more sense in my opinion is to publish the JAR of your multiplatform shared code in the local Maven repository and add it as a dependency on your Quarkus project: https://kotlinlang.org/docs/multiplatform-publish-lib.html

Also, take a look at #27242 issue that purpouse an enhancement/fix for reload the external JAR without need to restart Quarkus dev mode.

@aloubyansky Do you think this issue makes sense or is it better to close it for now?

@aloubyansky
Copy link
Member

We'll keep it open for now.

@andreas-eberle
Copy link
Contributor

I think this issue still makes sense. Being able to share DTOs of your API with the clients of your API is a great benefit of Kotlin Multiplatform and can remove a lot of code duplication. Therefore, it would be great have this properly supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/gradle Gradle area/kotlin kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants