Hey, sorry this is probably simple, but I just can...
# gradle
h
Hey, sorry this is probably simple, but I just cannot find the solution. I have a multiplatform project with submodules. So my
settings.gradle
looks like this :
Copy code
val rootProjects = listOf("common", "jsFrontend", "jvmBackend")

// Multiplatform roots
rootProjects.forEach {
    include(":$it")
}

// Server Submodules
include(":boot")
include(":core")
include(":api")
include(":persistence")
The boot module wires everything up and starts the actual server. So far so good, but now the thing is everything that isn't in the
build.gradle.kts
of the boot module is not on the classpath. That's also true for "dependencies of dependencies" so at runtime it says there is no jetty on the classpath even if ktor is added to the gradle file of boot. In a non-multiplatform project with the same sub-module structure it works and the boot gradle doesn't even need all dependencies. The submodules are all added to the boot gradle as well:
Copy code
kotlin {
    jvm("boot") {
        jvmToolchain(17)
        withJava()
    }
    sourceSets {
        @SuppressWarnings("unused")
        val bootMain by getting {
            kotlin.srcDir("src/main/kotlin")
            dependencies {
                implementation(project(":common"))
                implementation(project(":core"))

                implementation(project(":api"))
                implementation(project(":persistence"))
                // more dependencies here
            }
        }
    }
}
c
Can you show where you defined your Ktor dependency? It doesn't appear in your snippet
h
Hi, that would be directly beneath the project implementations where I made the comment. Also here the
api
submodule gradle:
Copy code
kotlin {
    jvm("api") {
        compilations.all {
            kotlinOptions.jvmTarget = "17"
        }
    }
    sourceSets {
        val apiMain by getting {
            kotlin.srcDir("src/main/kotlin")
            resources.srcDir("src/main/resources")
            dependencies {
                implementation(project(":common"))

                // BOM dependencies
                bomImplementation(Libs.okHttp3)
                bomImplementation(Libs.ktor)

                // Direct dependencies
                implementation(Libs.swaggerCore)

            }
        }
    }
}
c
What is
bomImplementation
? Is that something custom?
h
Yes it's from here: https://kotlinlang.slack.com/archives/C19FD9681/p1707138278822279?thread_ts=1706812781.833749&cid=C19FD9681 but I also tried with direct implementations, it didn't make a difference.
ktor libs are
"ktor-server-netty","ktor-server-core", "ktor-server-html-builder-jvm"
c
Can you run
./gradlew :api:dependencies
and paste here what apiMain's
implementation
configuration looks like
it's probably called something like
apiMainImplementation
, I don't remember by heart
h
Sorry someone called. I might not be able to answer. I need to configure java to run
gradlew
I don't know what you mean by apiMainImplementation, but I guess you mean
val apiMain by getting { }
from above?
c
How are you running Gradle tasks usually? (if you can't use
./gradlew
)
h
With the IntelliJ gradle tab
c
In the
:api
module, in "Tasks → Help" you should be able to find
dependencies
That will give you a very large report of all the dependencies actually configured in the module, and in which scope (called "configurations") they are available. One of the configurations should be called something like
apiMainImplementation
, I'm interested in what is configured in it
it should look somewhat like this:
Copy code
apiMainImplementation
\--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10
     +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.10
     |    +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10
     |    \--- org.jetbrains:annotations:13.0
     \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10
          \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.10 (*)
// all your other dependencies
h
Thank you very much for your help. Here is the apiMainImplementation excerpt:
Copy code
apiMainImplementation (n)
+--- project common (n)
+--- com.squareup.okhttp3:okhttp-bom:4.12.0 (n)
+--- com.squareup.okhttp3:okhttp (n)
+--- com.squareup.okhttp3:logging-interceptor (n)
+--- com.squareup.okhttp3:mockwebserver (n)
+--- io.ktor:ktor-server-jetty:2.3.8 (n)
+--- io.ktor:ktor-server-core:2.3.8 (n)
\--- io.swagger.core.v3:swagger-core:2.2.7 (n)
When I search for jetty I actually see it in the jetty dependencies, but they are not on the classpath or in external libraries tab
From the same output:
Copy code
|    +--- org.eclipse.jetty:jetty-server:11.0.13
|    |    +--- org.eclipse.jetty.toolchain:jetty-jakarta-servlet-api:5.0.2
|    |    +--- org.eclipse.jetty:jetty-http:11.0.13
|    |    |    +--- org.eclipse.jetty:jetty-util:11.0.13
|    |    |    |    \--- org.slf4j:slf4j-api:2.0.5
|    |    |    +--- org.eclipse.jetty:jetty-io:11.0.13
|    |    |    |    +--- org.slf4j:slf4j-api:2.0.5
|    |    |    |    \--- org.eclipse.jetty:jetty-util:11.0.13 (*)
|    |    |    \--- org.slf4j:slf4j-api:2.0.5
|    |    +--- org.eclipse.jetty:jetty-io:11.0.13 (*)
c
^ in which configuration is that excerpt from?
h
Sorry for the delay, it's from
apiRuntimeClasspath - Runtime classpath of api/main.
c
I'm a bit confused here. Can you try using regular
implementation
instead of your BOM method and diff the dependency list to see if it changes anything?
Also in general, I recommend sticking to the default behavior as much as possible, you're doing a lot of custom stuff 😅
h
Yeah I am also bummed a bit, but sadly I am not in a position to change it since the general structure is given by senior devs to have all products as similar as possible.
c
Ahah, can't say I agree.
I assume the project is not open source?
h
Not open source, no. 😕 But I will check your suggestion and make a demo project that I can share. That will take a little though. Thank you very much for your help so far. I'll post here asap.
c
Good luck 🙂
If you want to compare, this project of mine has many modules that depend on each other while declaring Ktor dependencies
h
Hey, thanks again for your help. While tinkering just now I was indeed able to find the culprit. IntelliJ IDEA. While in the IDE I didn't execute the project via
gradlew run
but via as a Kotlin Application. Now with the normal project structure IntelliJ is able to spin up the right way. But with the multiplatform stuff it doesn't. The other project doesn't have multiplatform so it wasn't an issue there. So the solution is to just do
./gradlew run
.
c
Ah, interesting. I recommend always creating run configurations of the Gradle type, it solves a few issues like that.
h
Yeah, I didn't even realise it. That would also explain why gradle build had no problems.